StringsListsHashesSetsSorted SetsBitmapsHyperLogLogStreams

Redis Data Structures

Redis's power comes from its data structures — Strings, Lists, Hashes, Sets, Sorted Sets, Bitmaps, HyperLogLog, and Streams. Learn when and why to use each.

35 min read9 sections
01

Why Data Structures Matter

Most developers first encounter Redis as a "fast key-value cache." You store a string, you get a string back, it's faster than your database. That mental model works for simple — but it misses what makes Redis genuinely powerful.

Redis is not a key-value store. It's a remote data structure server. Every key in Redis maps to a typed data structure — a list, a hash map, a sorted set, a stream — and Redis gives you atomic operations on those structures. This is the mental model shift that unlocks Redis's real capabilities.

🧰

The Toolbox vs The Hammer

Thinking of Redis as a key-value cache is like owning a full toolbox but only using the hammer. Yes, the hammer (Strings) works for many jobs. But when you need to maintain a leaderboard, a sorted set is a precision tool that does it in O(log N) with zero application code. When you need a job queue, a list with blocking pops gives you a reliable queue without deploying RabbitMQ. The data structures ARE the features — Redis just happens to serve them over the network at microsecond latency.

🔑 The Key Insight

In a traditional cache, you serialize your data to a string, store it, retrieve it, deserialize it, modify it in your application, re-serialize it, and store it again. With Redis data structures, you modify the data in-place on the server. HINCRBY increments a field in a hash without reading the whole object. ZADD inserts into a sorted set without fetching and re-sorting. The server does the work — your application just sends commands.

ApproachHow It WorksNetwork CallsAtomicity
Key-Value (serialize/deserialize)GET → deserialize → modify → serialize → SET2 (GET + SET)Not atomic — race conditions possible
Redis Data StructuresSingle command: HINCRBY, ZADD, LPUSH1Atomic — Redis is single-threaded per command

Quick Reference — Which Structure for Which Job

⚡ Simple Values & Counters

  • Strings — counters, , session tokens, caching
  • Bitmaps — boolean flags for millions of entities
  • HyperLogLog — approximate unique counts (12 KB fixed)

🗂️ Structured Data

  • Hashes — objects with partial read/write
  • Lists — queues, stacks, recent activity
  • Sets — unique collections, intersections
  • Sorted Sets — leaderboards, priority queues
  • Streams — event logs, reliable messaging
Mental Model — Cache vs Data Structure Servertext
Traditional cache (Memcached-style):
  Application: user = JSON.parse(cache.get("user:42"))
  Application: user.loginCount += 1
  Application: cache.set("user:42", JSON.stringify(user))
  Problem: if two servers do this simultaneously, one increment is lost.

Redis data structure server:
  Application: cache.hincrby("user:42", "loginCount", 1)
  Done. Atomic. No read-modify-write cycle. No race condition.
  Redis increments the field in-place on the server.

This pattern repeats for every data structure:
  Leaderboard?  ZADD / ZINCRBYsorted set handles ranking
  Job queue?    LPUSH / BRPOPlist handles FIFO ordering
  Unique count? PFADD / PFCOUNTHyperLogLog handles cardinality
  Feature flag? SET with NX/EXstring handles atomic check-and-set
1 / 9