Redis provides several data types optimized for different use cases. Here's when and how to use each.
The simplest type. Can hold text, numbers, or binary data up to 512MB.
// SET - store a value await redis.set('key', 'value'); await redis.set('key', 'value', 'EX', 3600); // Expires in 1 hour // GET - retrieve a value const value = await redis.get('key'); // INCR/DECR - atomic counters await redis.incr('counter'); await redis.incrby('counter', 10); await redis.decr('counter'); // MGET/MSET - multiple keys await redis.mset('key1', 'val1', 'key2', 'val2'); const [v1, v2] = await redis.mget('key1', 'key2'); // SETNX - set only if not exists const wasSet = await redis.setnx('lock', 'holder'); // SETEX - set with expiry await redis.setex('session', 3600, 'data');
Key-value pairs within a key. Perfect for objects.
// HSET - set field(s) await redis.hset('user:123', 'name', 'Alice'); await redis.hset('user:123', { name: 'Alice', email: 'alice@example.com', age: '30' }); // HGET - get a field const name = await redis.hget('user:123', 'name'); // HGETALL - get all fields const user = await redis.hgetall('user:123'); // { name: 'Alice', email: 'alice@example.com', age: '30' } // HMGET - get multiple fields const [name, email] = await redis.hmget('user:123', 'name', 'email'); // HINCRBY - increment numeric field await redis.hincrby('user:123', 'loginCount', 1); // HDEL - delete field(s) await redis.hdel('user:123', 'temporaryField'); // HEXISTS - check if field exists const exists = await redis.hexists('user:123', 'name'); // HKEYS/HVALS - get all keys or values const fields = await redis.hkeys('user:123'); const values = await redis.hvals('user:123');
stats:daily {views: 100, clicks: 50}
Ordered sequences. Add/remove from both ends.
// LPUSH/RPUSH - add to left/right await redis.lpush('queue', 'item1'); // Add to front await redis.rpush('queue', 'item2'); // Add to back // LPOP/RPOP - remove from left/right const item = await redis.lpop('queue'); const item = await redis.rpop('queue'); // BRPOP/BLPOP - blocking pop (for queues) const [key, value] = await redis.brpop('queue', 30); // Wait up to 30s // LRANGE - get range of elements const items = await redis.lrange('queue', 0, -1); // All items const recent = await redis.lrange('feed', 0, 9); // First 10 // LLEN - get length const length = await redis.llen('queue'); // LINDEX - get element by index const item = await redis.lindex('queue', 0); // LTRIM - keep only a range await redis.ltrim('recent', 0, 99); // Keep first 100
Unordered collections of unique strings.
// SADD - add member(s) await redis.sadd('tags:article:1', 'redis', 'database', 'nosql'); // SREM - remove member(s) await redis.srem('tags:article:1', 'nosql'); // SMEMBERS - get all members const tags = await redis.smembers('tags:article:1'); // SISMEMBER - check membership const hasTag = await redis.sismember('tags:article:1', 'redis'); // SCARD - count members const count = await redis.scard('tags:article:1'); // SINTER - intersection of sets const common = await redis.sinter('user:1:friends', 'user:2:friends'); // SUNION - union of sets const all = await redis.sunion('set1', 'set2'); // SDIFF - difference of sets const unique = await redis.sdiff('user:1:friends', 'user:2:friends'); // SRANDMEMBER - random member(s) const random = await redis.srandmember('users', 5); // SPOP - remove and return random const winner = await redis.spop('raffle');
Like sets, but each member has a score for ordering.
// ZADD - add with score await redis.zadd('leaderboard', 100, 'player1'); await redis.zadd('leaderboard', { player1: 100, player2: 200 }); // ZSCORE - get score const score = await redis.zscore('leaderboard', 'player1'); // ZINCRBY - increment score await redis.zincrby('leaderboard', 10, 'player1'); // ZRANK/ZREVRANK - get rank (0-indexed) const rank = await redis.zrevrank('leaderboard', 'player1'); // Highest first // ZRANGE/ZREVRANGE - get by rank const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES'); // ZRANGEBYSCORE - get by score range const highScorers = await redis.zrangebyscore('leaderboard', 100, '+inf'); // ZREM - remove member await redis.zrem('leaderboard', 'player1'); // ZCARD - count members const count = await redis.zcard('leaderboard'); // ZCOUNT - count in score range const elite = await redis.zcount('leaderboard', 1000, '+inf');
Append-only log data structure. Ideal for event sourcing.
// XADD - add entry const id = await redis.xadd('events', '*', 'type', 'click', 'userId', '123'); // XREAD - read entries const entries = await redis.xread('COUNT', 10, 'STREAMS', 'events', '0'); // XREAD BLOCK - blocking read const entries = await redis.xread('BLOCK', 5000, 'STREAMS', 'events', '$'); // XRANGE - get range by ID const entries = await redis.xrange('events', '-', '+', 'COUNT', 100); // XLEN - count entries const count = await redis.xlen('events'); // Consumer Groups await redis.xgroup('CREATE', 'events', 'mygroup', '$', 'MKSTREAM'); // Read as consumer const entries = await redis.xreadgroup( 'GROUP', 'mygroup', 'consumer1', 'COUNT', 10, 'STREAMS', 'events', '>' ); // Acknowledge processing await redis.xack('events', 'mygroup', entryId);
Data Types
Redis provides several data types optimized for different use cases. Here's when and how to use each.
Quick Reference#
Strings#
The simplest type. Can hold text, numbers, or binary data up to 512MB.
Common Commands#
// SET - store a value await redis.set('key', 'value'); await redis.set('key', 'value', 'EX', 3600); // Expires in 1 hour // GET - retrieve a value const value = await redis.get('key'); // INCR/DECR - atomic counters await redis.incr('counter'); await redis.incrby('counter', 10); await redis.decr('counter'); // MGET/MSET - multiple keys await redis.mset('key1', 'val1', 'key2', 'val2'); const [v1, v2] = await redis.mget('key1', 'key2'); // SETNX - set only if not exists const wasSet = await redis.setnx('lock', 'holder'); // SETEX - set with expiry await redis.setex('session', 3600, 'data');Use Cases#
Memory#
Hashes#
Key-value pairs within a key. Perfect for objects.
Common Commands#
// HSET - set field(s) await redis.hset('user:123', 'name', 'Alice'); await redis.hset('user:123', { name: 'Alice', email: 'alice@example.com', age: '30' }); // HGET - get a field const name = await redis.hget('user:123', 'name'); // HGETALL - get all fields const user = await redis.hgetall('user:123'); // { name: 'Alice', email: 'alice@example.com', age: '30' } // HMGET - get multiple fields const [name, email] = await redis.hmget('user:123', 'name', 'email'); // HINCRBY - increment numeric field await redis.hincrby('user:123', 'loginCount', 1); // HDEL - delete field(s) await redis.hdel('user:123', 'temporaryField'); // HEXISTS - check if field exists const exists = await redis.hexists('user:123', 'name'); // HKEYS/HVALS - get all keys or values const fields = await redis.hkeys('user:123'); const values = await redis.hvals('user:123');Use Cases#
stats:daily {views: 100, clicks: 50}Memory#
Lists#
Ordered sequences. Add/remove from both ends.
Common Commands#
// LPUSH/RPUSH - add to left/right await redis.lpush('queue', 'item1'); // Add to front await redis.rpush('queue', 'item2'); // Add to back // LPOP/RPOP - remove from left/right const item = await redis.lpop('queue'); const item = await redis.rpop('queue'); // BRPOP/BLPOP - blocking pop (for queues) const [key, value] = await redis.brpop('queue', 30); // Wait up to 30s // LRANGE - get range of elements const items = await redis.lrange('queue', 0, -1); // All items const recent = await redis.lrange('feed', 0, 9); // First 10 // LLEN - get length const length = await redis.llen('queue'); // LINDEX - get element by index const item = await redis.lindex('queue', 0); // LTRIM - keep only a range await redis.ltrim('recent', 0, 99); // Keep first 100Use Cases#
Memory#
Sets#
Unordered collections of unique strings.
Common Commands#
// SADD - add member(s) await redis.sadd('tags:article:1', 'redis', 'database', 'nosql'); // SREM - remove member(s) await redis.srem('tags:article:1', 'nosql'); // SMEMBERS - get all members const tags = await redis.smembers('tags:article:1'); // SISMEMBER - check membership const hasTag = await redis.sismember('tags:article:1', 'redis'); // SCARD - count members const count = await redis.scard('tags:article:1'); // SINTER - intersection of sets const common = await redis.sinter('user:1:friends', 'user:2:friends'); // SUNION - union of sets const all = await redis.sunion('set1', 'set2'); // SDIFF - difference of sets const unique = await redis.sdiff('user:1:friends', 'user:2:friends'); // SRANDMEMBER - random member(s) const random = await redis.srandmember('users', 5); // SPOP - remove and return random const winner = await redis.spop('raffle');Use Cases#
Memory#
Sorted Sets#
Like sets, but each member has a score for ordering.
Common Commands#
// ZADD - add with score await redis.zadd('leaderboard', 100, 'player1'); await redis.zadd('leaderboard', { player1: 100, player2: 200 }); // ZSCORE - get score const score = await redis.zscore('leaderboard', 'player1'); // ZINCRBY - increment score await redis.zincrby('leaderboard', 10, 'player1'); // ZRANK/ZREVRANK - get rank (0-indexed) const rank = await redis.zrevrank('leaderboard', 'player1'); // Highest first // ZRANGE/ZREVRANGE - get by rank const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES'); // ZRANGEBYSCORE - get by score range const highScorers = await redis.zrangebyscore('leaderboard', 100, '+inf'); // ZREM - remove member await redis.zrem('leaderboard', 'player1'); // ZCARD - count members const count = await redis.zcard('leaderboard'); // ZCOUNT - count in score range const elite = await redis.zcount('leaderboard', 1000, '+inf');Use Cases#
Memory#
Streams#
Append-only log data structure. Ideal for event sourcing.
Common Commands#
// XADD - add entry const id = await redis.xadd('events', '*', 'type', 'click', 'userId', '123'); // XREAD - read entries const entries = await redis.xread('COUNT', 10, 'STREAMS', 'events', '0'); // XREAD BLOCK - blocking read const entries = await redis.xread('BLOCK', 5000, 'STREAMS', 'events', '$'); // XRANGE - get range by ID const entries = await redis.xrange('events', '-', '+', 'COUNT', 100); // XLEN - count entries const count = await redis.xlen('events'); // Consumer Groups await redis.xgroup('CREATE', 'events', 'mygroup', '$', 'MKSTREAM'); // Read as consumer const entries = await redis.xreadgroup( 'GROUP', 'mygroup', 'consumer1', 'COUNT', 10, 'STREAMS', 'events', '>' ); // Acknowledge processing await redis.xack('events', 'mygroup', entryId);Use Cases#
Memory#
Choosing the Right Type#