Redis has hundreds of commands, and you will use about twenty-five of them ninety-five percent of the time. The trick to remembering them is that they are organized by the data type they operate on: string commands, hash commands, list commands, set commands, plus a handful of key-management and expiry commands that work across everything. Learn the groups and the individual commands stop being a list to memorize and start being obvious - the command name tells you the type it belongs to.
This is the working set, grouped the way Redis actually organizes them, with the daily-driver commands and the couple of traps that catch people in production.
Table of contents
- Keys and expiry: the cross-type commands
- Strings and counters
- Hashes, lists, and sets
- Introspection and safety
- The commands worth never running blind
- How this fits the rest of the stack
- FAQ
Keys and expiry: the cross-type commands
SET user:1 "Ada" # set a key
GET user:1 # read it
DEL user:1 # delete it
EXISTS user:1 # 1 if present, 0 if not
EXPIRE user:1 3600 # expire in 1 hour
TTL user:1 # seconds left, -1 no expiry, -2 gone
KEYS user:* # DANGER - scans everything, blocks the server
SCAN 0 MATCH user:* # the safe, cursor-based alternative
The one trap here is KEYS. It is fine on your laptop and a production incident on a large database - it blocks the single-threaded server while it walks every key. Use SCAN in any code that runs against a real dataset. This is the single most common Redis mistake.
Strings and counters
SET page:views 0
INCR page:views # atomic +1, returns new value
INCRBY page:views 10 # atomic +10
DECR page:views # atomic -1
APPEND log:1 "line\n" # append to a string
SETEX session:1 900 "..." # set with a 900s TTL in one command
SETNX lock:1 "held" # set only if absent - a simple lock primitive
INCR is atomic, which is the whole reason to use Redis for counters instead of read-modify-write against a database. SETEX and SETNX combine two operations into one atomic step - use them rather than a separate SET plus EXPIRE, which has a race window between the two calls.
Hashes, lists, and sets
# Hash - a record with fields
HSET user:1 name "Ada" age 36
HGET user:1 name
HGETALL user:1
# List - ordered, good as a queue
LPUSH queue:jobs "job1" # push left
RPOP queue:jobs # pop right -> FIFO queue
LRANGE queue:jobs 0 -1 # view all
# Set - unique members
SADD tags:1 "redis" "cache"
SISMEMBER tags:1 "redis" # 1 if present
SMEMBERS tags:1
Hashes model records without serializing JSON into a string. Lists with LPUSH + RPOP give you a simple, reliable FIFO queue. Sets enforce uniqueness and support fast membership tests. Reaching for the right structure here is what separates using Redis from abusing it as a key-value dumping ground.
Introspection and safety
TYPE user:1 # what data type is this key?
DBSIZE # how many keys total
INFO memory # memory usage and stats
MEMORY USAGE user:1 # bytes used by one key
FLUSHDB # DANGER - wipes the current database
INFO and MEMORY USAGE are how you answer ‘why is Redis using so much RAM’ - almost always a few key patterns without expiry. FLUSHDB and FLUSHALL are the commands to fear: they delete everything, instantly, with no undo. Rename or disable them in production configs if you can.
The commands worth never running blind
KEYS *on a large database - blocks the server. UseSCAN.FLUSHALL/FLUSHDB- wipes data with no confirmation. Treat likerm -rf.SAVE- blocks the server while it writes the dump. UseBGSAVEfor a background save.
Redis is single-threaded for command execution, so any one slow command stalls every other client. That single fact explains most Redis performance incidents, and respecting it is most of what ‘knowing Redis’ means in practice.
How this fits the rest of the stack
Knowing which Redis commands are safe at scale and which block the server is the difference between a cache that helps and one that becomes the incident. That is a sizing question too - how much memory the working set needs, and what happens when keys never expire. The RunxBuild hosting calculator puts a Redis-backed service, its database, and memory on the table as line items, and the RunxBuild dashboard is where you watch memory and command latency once it is live.
Useful related references:
- The Redis CLI: a practical tour
- Redis default port and how to change it
- Redis EXPIRE and key TTLs
- Databases on RunxBuild
FAQ
What are the most common Redis commands?
The daily set is SET, GET, DEL, and EXISTS for strings; INCR and DECR for counters; HSET, HGET, and HGETALL for hashes; LPUSH and RPOP for list queues; SADD and SMEMBERS for sets; and EXPIRE and TTL for expiry. Across types, SCAN safely iterates keys and INFO reports stats. That group covers the vast majority of real usage.
Why is the KEYS command dangerous in Redis?
Because Redis executes commands on a single thread, and KEYS walks the entire keyspace before returning, blocking every other client for the duration. On a large production database that is an outage. Use SCAN instead: it returns keys in small batches via a cursor, so the server stays responsive. KEYS is fine only on small or local datasets.
How do I set an expiry on a Redis key?
Use EXPIRE key seconds to set a TTL on an existing key, or SETEX key seconds value to set a string and its TTL in one atomic command. Check remaining time with TTL key, which returns the seconds left, -1 if the key has no expiry, or -2 if it no longer exists. Combining SET and EXPIRE separately leaves a race window, so prefer SETEX.
What is the difference between INCR and updating a counter in a database?
INCR is atomic on Redis’s single thread, so concurrent increments never lose updates and you avoid the read-modify-write race you get updating a row in most databases without explicit locking. That atomicity, plus in-memory speed, is the main reason to use Redis for counters, rate limits, and similar high-frequency numeric updates.
Which Redis commands should I avoid in production?
Avoid KEYS on large datasets (use SCAN), SAVE which blocks while dumping (use BGSAVE), and FLUSHDB or FLUSHALL which wipe data instantly with no undo. All are risky because Redis runs commands on one thread, so a slow or destructive command affects every client. Consider renaming or disabling the destructive ones in your production configuration.