> ## Documentation Index
> Fetch the complete documentation index at: https://cache-pot.thatdevguy.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Key commands: DEL, EXPIRE, TTL, SCAN, TYPE, RENAME

> Reference for Cache-Pot generic key commands: DEL, EXISTS, EXPIRE, TTL, PERSIST, KEYS, SCAN, TYPE, RENAME, RENAMENX, MEMORY.

These commands operate on keys regardless of their type. You use them to delete keys, manage expiry, iterate the keyspace, inspect a key's type, rename keys, and measure memory consumption. Because they work across all data types, they're the building blocks for housekeeping routines, cache eviction policies, and operational dashboards.

***

### DEL

Deletes one or more keys. Keys that do not exist are silently ignored.

**Syntax:** `DEL key [key ...]`

```redis theme={null}
SET a 1
SET b 2

DEL a b nonexistent
# (integer) 2  (only a and b existed)
```

**Returns:** Integer — the number of keys that were actually deleted.

***

### EXISTS

Returns how many of the specified keys currently exist. You can name the same key multiple times and it will be counted once per occurrence.

**Syntax:** `EXISTS key [key ...]`

```redis theme={null}
SET x 10
EXISTS x y x
# (integer) 2  (x counted twice, y missing)
```

**Returns:** Integer — count of the keys that exist.

***

### EXPIRE

Sets a time-to-live on `key` in seconds. After the timeout elapses, the key is automatically deleted. Any existing TTL is replaced.

**Syntax:** `EXPIRE key seconds`

```redis theme={null}
SET session "abc123"
EXPIRE session 3600

TTL session
# (integer) 3600  (approx.)
```

**Returns:** `1` if the timeout was set, `0` if the key does not exist.

***

### PEXPIRE

Sets a time-to-live on `key` in milliseconds.

**Syntax:** `PEXPIRE key milliseconds`

```redis theme={null}
SET lock "held"
PEXPIRE lock 500
# (integer) 1
```

**Returns:** `1` if the timeout was set, `0` if the key does not exist.

***

### EXPIREAT

Sets the expiry of `key` to an absolute Unix timestamp in seconds.

**Syntax:** `EXPIREAT key unix-seconds`

```redis theme={null}
EXPIREAT promo 1735689600
# (integer) 1
```

**Returns:** `1` if the timeout was set, `0` if the key does not exist.

***

### PEXPIREAT

Sets the expiry of `key` to an absolute Unix timestamp in milliseconds.

**Syntax:** `PEXPIREAT key unix-milliseconds`

```redis theme={null}
PEXPIREAT token 1735689600000
# (integer) 1
```

**Returns:** `1` if the timeout was set, `0` if the key does not exist.

***

### TTL

Returns the remaining time-to-live of `key` in seconds.

**Syntax:** `TTL key`

```redis theme={null}
SET greeting "hello"
EXPIRE greeting 120

TTL greeting
# (integer) 119  (approx.)

TTL persistent_key
# (integer) -1  (no TTL set)

TTL missing_key
# (integer) -2  (key does not exist)
```

**Returns:** Seconds remaining as an integer. Returns `-1` if the key exists but has no TTL. Returns `-2` if the key does not exist.

***

### PTTL

Returns the remaining time-to-live of `key` in milliseconds.

**Syntax:** `PTTL key`

```redis theme={null}
SET temp "value"
PEXPIRE temp 5000

PTTL temp
# (integer) 4998  (approx.)
```

**Returns:** Milliseconds remaining. Returns `-1` for no TTL; `-2` if the key does not exist.

***

### PERSIST

Removes the TTL from `key`, making it persistent. Has no effect on keys that have no TTL.

**Syntax:** `PERSIST key`

```redis theme={null}
SET item "data"
EXPIRE item 60

PERSIST item
# (integer) 1

TTL item
# (integer) -1  (TTL removed)
```

**Returns:** `1` if the TTL was removed, `0` if the key does not exist or had no TTL.

***

### KEYS

Returns all keys matching a glob pattern. Supported wildcards: `*` (any sequence), `?` (any single character), `[...]` (character class).

**Syntax:** `KEYS pattern`

```redis theme={null}
SET user:1 "Alice"
SET user:2 "Bob"
SET config "default"

KEYS user:*
# 1) "user:1"
# 2) "user:2"

KEYS *
# (all keys)
```

**Returns:** Array of matching key names.

<Warning>
  `KEYS` scans the entire keyspace and blocks the server while it runs. On large datasets this can cause significant latency spikes. Use `SCAN` in production instead.
</Warning>

***

### SCAN

Incrementally iterates the keyspace without blocking the server. Start with cursor `0`; repeat using the cursor returned in each response until the server returns cursor `0` again, signalling that a complete iteration has finished.

**Syntax:** `SCAN cursor [MATCH pattern] [COUNT n] [TYPE type]`

<ParamField path="cursor" type="integer" required>
  Start at `0` to begin a new scan. Use the cursor returned by the previous call to continue.
</ParamField>

<ParamField path="MATCH pattern" type="string">
  Filter keys by glob pattern (default `*`).
</ParamField>

<ParamField path="COUNT n" type="integer">
  Hint for how many keys to examine per call (default 10). This is an approximation — the actual number of keys returned may differ.
</ParamField>

<ParamField path="TYPE type" type="string">
  Filter by key type. Valid values: `string`, `hash`, `list`, `set`, `zset`, `vector`.
</ParamField>

```redis theme={null}
# Iterate through all user: keys in batches of 100
SCAN 0 MATCH user:* COUNT 100
# 1) "128"           <- next cursor (not done yet)
# 2) 1) "user:1"
#    2) "user:2"
#    3) ...

SCAN 128 MATCH user:* COUNT 100
# 1) "0"             <- cursor 0 means the full scan is complete
# 2) 1) "user:99"
#    2) "user:100"
```

**Returns:** Two-element array: `[next_cursor, [key, key, ...]]`. When `next_cursor` is `"0"`, the iteration is complete.

***

### HSCAN / SSCAN / ZSCAN

Incrementally iterate the fields of a hash, the members of a set, or the members-and-scores of a sorted set, using the same cursor protocol as `SCAN`.

**Syntax:**

* `HSCAN key cursor [MATCH pattern] [COUNT n]`
* `SSCAN key cursor [MATCH pattern] [COUNT n]`
* `ZSCAN key cursor [MATCH pattern] [COUNT n]`

```redis theme={null}
HSET product:1 name "Widget" price "9.99" stock "42"
HSCAN product:1 0
# 1) "0"
# 2) 1) "name"
#    2) "Widget"
#    3) "price"
#    4) "9.99"
#    5) "stock"
#    6) "42"
```

**Returns:** Two-element array `[next_cursor, items]`. `HSCAN` and `ZSCAN` return interleaved field/value or member/score pairs; `SSCAN` returns plain member strings.

***

### TYPE

Returns the type of the value stored at `key`.

**Syntax:** `TYPE key`

```redis theme={null}
SET mystr "hello"
TYPE mystr
# string

LPUSH mylist "a"
TYPE mylist
# list

TYPE nonexistent
# none
```

**Returns:** One of: `string`, `hash`, `list`, `set`, `zset`, `vector`, or `none` if the key does not exist.

***

### RENAME

Renames `key` to `newkey`. If `newkey` already exists, it is overwritten. The TTL of the original key is preserved on the renamed key. Returns an error if `key` does not exist.

**Syntax:** `RENAME key newkey`

```redis theme={null}
SET old_name "value"
RENAME old_name new_name
# OK

GET new_name
# "value"
```

**Returns:** `OK` on success, or an error if the source key does not exist.

***

### RENAMENX

Renames `key` to `newkey` only if `newkey` does not already exist. This is the atomic, non-destructive variant of `RENAME`.

**Syntax:** `RENAMENX key newkey`

```redis theme={null}
SET source "data"
SET target "existing"

RENAMENX source target
# (integer) 0  (target exists, no rename)

RENAMENX source free_name
# (integer) 1  (renamed)
```

**Returns:** `1` if the rename succeeded, `0` if `newkey` already exists. Returns an error if the source key does not exist.

***

### MEMORY USAGE

Returns the approximate number of bytes that `key` and its value consume in memory. The `SAMPLES` option is accepted for compatibility with Redis tooling but is ignored — Cache-Pot always walks the full value.

**Syntax:** `MEMORY USAGE key [SAMPLES n]`

```redis theme={null}
SET bigval "x"
MEMORY USAGE bigval
# (integer) 56

MEMORY USAGE nonexistent
# (nil)
```

**Returns:** Integer byte count, or nil if the key does not exist.

<Tip>
  `MEMORY USAGE` reports a heuristic estimate, not an exact allocator measurement. Use it for relative comparisons and capacity planning rather than precise accounting.
</Tip>
