SCAN is not KEYS, and the difference is an outage

KEYS blocks the server for the duration of a full keyspace walk, and Redis is single-threaded, so it blocks everything.

# never, on anything with data in it
KEYS session:*

# cursor-based, ~10ms per call
SCAN 0 MATCH 'session:*' COUNT 500

# guarantees: every key present for the whole scan is
#   returned at least once. keys added or removed during
#   the scan may or may not appear. duplicates happen.

The at-least-once guarantee means any script acting on scan results has to be idempotent, and the duplicates are not rare on a keyspace being resized during the walk. MATCH filters after retrieval, so a scan for a rare prefix still walks the whole keyspace — the count of keys examined is unrelated to the count returned, which surprises people timing it. Keeping an index set of the keys you care about is the answer when this becomes a routine need.