Skip to content

SCAN & Key Operations

These commands operate on any key regardless of its type.

Returns 1 if the key exists, 0 if it does not. You can check multiple keys at once — the return value is the count of keys that exist.

127.0.0.1:6379> SET user:1 "Ada"
OK
127.0.0.1:6379> EXISTS user:1
(integer) 1
127.0.0.1:6379> EXISTS user:99
(integer) 0
127.0.0.1:6379> EXISTS user:1 user:99 user:1
(integer) 2

Deletes one or more keys. Returns the count of keys that were actually deleted (keys that did not exist are not counted).

127.0.0.1:6379> SET a "1"
OK
127.0.0.1:6379> SET b "2"
OK
127.0.0.1:6379> DEL a b nonexistent
(integer) 2
127.0.0.1:6379> EXISTS a
(integer) 0

Returns the data type of the value stored at a key: string, list, set, zset, hash, or stream.

127.0.0.1:6379> SET mystr "hello"
OK
127.0.0.1:6379> TYPE mystr
string
127.0.0.1:6379> TYPE nonexistent:key
none

Renames a key. If the destination key already exists, it is overwritten. Use RENAMENX to rename only if the destination does not exist.

127.0.0.1:6379> SET old:key "value"
OK
127.0.0.1:6379> RENAME old:key new:key
OK
127.0.0.1:6379> EXISTS old:key
(integer) 0
127.0.0.1:6379> GET new:key
"value"
SET user:1 "Ada"
EXISTS user:1
EXISTS user:99
SET a "1"
SET b "2"
DEL a b nonexistent
SET mystr "hello"
TYPE mystr
SET old:key "value"
RENAME old:key new:key
GET new:key

KEYS — and why you must not use it in production

Section titled “KEYS — and why you must not use it in production”

KEYS pattern returns all keys matching a glob-style pattern. It is very convenient for development and debugging.

127.0.0.1:6379> MSET user:1 "Ada" user:2 "Bob" session:abc "tok" session:xyz "tok2"
OK
127.0.0.1:6379> KEYS user:*
1) "user:2"
2) "user:1"
127.0.0.1:6379> KEYS *
1) "user:2"
2) "user:1"
3) "session:abc"
4) "session:xyz"

KEYS is a blocking, O(N) scan of the entire keyspace. On a Redis server with millions of keys it can take seconds, blocking every other client for the duration. Never run it against a production server — use SCAN instead.

SCAN is a cursor-based iterator. Each call processes a small batch of keys and returns:

  1. A new cursor (to pass to the next call)
  2. A list of keys from this batch

When the returned cursor is 0, the iteration is complete.

127.0.0.1:6379> MSET k1 a k2 b k3 c k4 d k5 e k6 f k7 g k8 h k9 i k10 j
OK
127.0.0.1:6379> SCAN 0 MATCH k* COUNT 3
1) "7"
2) 1) "k9"
2) "k3"
3) "k1"
127.0.0.1:6379> SCAN 7 MATCH k* COUNT 3
1) "4"
2) 1) "k8"
2) "k2"
127.0.0.1:6379> SCAN 4 MATCH k* COUNT 3
1) "0"
2) 1) "k10"
2) "k4"
3) "k7"
4) "k5"
5) "k6"

COUNT is a hint, not a hard limit — Redis may return more or fewer keys per call. The iteration always completes when the cursor returns to 0.

MSET k1 a k2 b k3 c k4 d k5 e k6 f k7 g k8 h k9 i k10 j
SCAN 0 MATCH k* COUNT 3
SCAN 0 MATCH k* COUNT 100
OptionDescription
MATCH patternFilter results by glob pattern (filtering happens after sampling)
COUNT hintSuggest how many items to sample per call (default 10)
TYPE typeOnly return keys of a specific type (Redis 6.0+)

A practical full-scan loop in a script looks like:

127.0.0.1:6379> SCAN 0 MATCH session:* COUNT 100
1) "42"
2) 1) "session:abc"
127.0.0.1:6379> SCAN 42 MATCH session:* COUNT 100
1) "0"
2) 1) "session:xyz"

Keep calling SCAN with the returned cursor until the cursor comes back as 0. Collect results across all iterations.

SCAN 0 MATCH session:* COUNT 100
What does SCAN return when the full iteration is complete?
Why is KEYS dangerous on a production Redis server?
What does EXISTS user:1 user:1 user:2 return if user:1 exists and user:2 does not?
What does TYPE return for a key that does not exist?