BlogRedis

Redis Architecture: How Redis Works Inside

Scott Sternloff

By Scott Sternloff, Senior Enterprise Architect

LinkedIn · Updated · 7 min read

Redis Architecture: How Redis Works Inside
On this page

Redis is a single server process that keeps the whole dataset in memory and executes commands one at a time on a main thread, driven by an event loop that multiplexes every client connection. Around that core sit background threads for slow disk work, optional I/O threads for network reads and writes, compact encodings for small values, two persistence mechanisms, asynchronous replication, and two ways to add failover: Sentinel and Cluster.

This page explains how those parts fit together and what each one means in production. For what teams use Redis for, see what Redis is used for.

The event loop and single-threaded command execution

Redis's documentation describes a mostly single-threaded design: one process serves all clients through multiplexing and executes requests sequentially. Every command is atomic without locks.

It also sets the main operational rule: a slow command blocks everyone. KEYS * on a large keyspace, a long Lua script or DEL on a huge key holds the main thread until it finishes. Use SCAN, bounded ranges and UNLINK, and watch SLOWLOG.

"Mostly" covers three exceptions that never execute commands:

  • Background threads, used since Redis 2.4 for slow disk operations such as the AOF fsync, and since 4.0 for lazy freeing: UNLINK and the lazyfree-lazy-* options release memory off the main thread.
  • Forked child processes that write RDB snapshots and rewrite the AOF. The fork itself runs on the main thread and can pause it.
  • I/O threads, covered next.

I/O threads in Redis 6 and Redis 8

Redis 6.0 added optional threaded I/O, set with io-threads: extra threads wrote replies to sockets, and reading and parsing requests needed io-threads-do-reads as well. Redis 8.0 replaced it with a new implementation in which the threads always handle both reads and writes, and io-threads-do-reads no longer has any effect. In both versions commands still execute on the main thread.

# redis.conf: try 3 threads on a 4-core machine, 7 on 8 cores
io-threads 4

The guidance in redis.conf is to enable threading only on machines with at least four cores, leaving one spare, and only when Redis is using a large share of CPU time. Beyond that, the way to use more cores is more instances or Redis Cluster.

Data structures and encodings

Every value has a type and an internal encoding, visible with OBJECT ENCODING key. Small values use compact encodings; Redis converts them to the general encoding once they grow past the *-max-listpack-entries and *-max-listpack-value thresholds or an operation needs it.

TypeCompact encodingGeneral encoding
Stringint for 64-bit integers; embstr up to 44 bytesraw
Listlistpack (Redis 7.0 and later)quicklist, a linked list of listpacks
Setintset for integers; listpack (Redis 7.2 and later)hashtable
Hashlistpack (Redis 7.0 and later)hashtable
Sorted setlistpack (Redis 7.0 and later)skiplist
Streamn/aRadix tree of listpacks

Listpack replaced ziplist in Redis 7.0. Compact encodings take far less memory than hash tables or skiplists; raising the thresholds trades CPU per access for that saving.

The memory model

The whole dataset lives in RAM, so memory is the capacity limit. On Linux Redis is built with jemalloc by default, chosen because it fragments less than libc malloc. maxmemory caps the dataset and the eviction policy decides what happens at the cap. Redis's administration guide says to leave room for overhead and fragmentation (with 10 GB free, set 8 or 9 GB), and a write-heavy instance can use up to twice its normal memory during a snapshot. The Redis memory guide covers the details.

Persistence, briefly

Redis can write the dataset to disk as RDB snapshots, an append-only file, or both, so a restart does not start empty. Both use a forked child, which is why persistence affects latency and memory. Our Redis persistence guide covers RDB vs AOF, the fsync options and what breaks in production.

Replication

Replication is asynchronous. The primary streams its writes to replicas, which are read-only by default, and does not wait for them. Each dataset history has a replication ID, and each byte of the stream advances an offset:

  • Partial resync. A replica that reconnects sends its replication ID and offset with PSYNC and receives only what it missed, if the primary's backlog (repl-backlog-size, 1 MB by default) still holds it.
  • Full sync. Otherwise the primary forks, produces an RDB snapshot and sends it, then streams the writes buffered meanwhile. Since Redis 7.0 the snapshot goes straight to the socket by default (repl-diskless-sync yes).

WAIT lets a client wait for a number of replicas to acknowledge its writes, but Redis's documentation is explicit that this does not make the system strongly consistent: acknowledged writes can still be lost in a failover.

High availability: Sentinel vs Cluster

Replication alone does not fail over. Two built-in options add that:

Redis SentinelRedis Cluster
Data layoutOne primary holds everything, with replicasKeyspace split into 16,384 hash slots across several primaries, each with replicas
FailoverSeparate Sentinel processes monitor, agree and promote a replica; Redis says to run at least threeBuilt into the nodes, with no separate process
Client viewAsks Sentinel for the current primaryKeeps a slot map and follows MOVED and ASK redirects
LimitsWrite rate and dataset bounded by one nodeMulti-key commands only within one slot; database 0 only

Choose Sentinel while one node holds the data with headroom, and Cluster when it does not. Our Redis Cluster guide covers hash slots and resharding, and Redis high availability walks through the failover sequence for both.

Where Valkey diverged

Valkey forked Redis 7.2.4 in 2024 and kept its architecture. It has since diverged in a few places:

  • I/O threading (Valkey 8.0, September 2024). Valkey wrote its own asynchronous model rather than adopting Redis 8's. The main thread hands jobs to I/O threads: reading and parsing commands, writing replies, polling sockets with epoll_wait and freeing memory. It scales the number of active threads with load. Command execution stays single-threaded.
  • Dual-channel replication (Valkey 8.0). During a full sync the RDB snapshot travels on a separate connection from the stream of new writes. It is off by default (dual-channel-replication-enabled no).
  • A new key table (Valkey 8.1, March 2025). Valkey replaced the main dictionary, and the hash, set and sorted set implementations, with a more memory-efficient hash table.
  • Data files. Valkey reads RDB and AOF files from Redis OSS 7.2 and earlier, but not files written by Redis 7.4 and later.

For most applications the protocol and commands are the same. Our Valkey vs Redis comparison covers licensing and feature differences, and Redis end of life lists which Redis versions still receive fixes.

When to get help

Most Redis incidents trace back to the architecture: a slow command holding the main thread, a fork stalling a large instance, or a full sync looping. AceMQ provides Redis support for open-source Redis and Valkey support for the fork, and Redis managed services if you would rather we run it.

Sources

Frequently Asked Questions

Is Redis single-threaded?

Command execution is. One main thread runs every command in sequence. Redis has used background threads for slow disk work since 2.4 and for lazy freeing since 4.0, and it can use I/O threads for network reads and writes: optional since Redis 6.0, with a new implementation in Redis 8.0.

Why is Redis fast if commands run on one thread?

The data is already in memory, so no command waits on a disk read, and running commands one at a time needs no locks. The event loop multiplexes thousands of connections on that thread. The cost is that one slow command delays every other client.

What are Redis I/O threads?

Threads, enabled with io-threads, that read and parse requests and write replies so the main thread spends its time executing commands. Redis suggests them only on machines with at least four cores, leaving one spare, and only when Redis is using a large share of a core.

How does Redis replication work?

Asynchronously. The primary streams its writes to replicas and tracks progress with a replication ID and offset. A replica that reconnects asks for the part it missed from the backlog; if that is no longer available, it gets a full copy as an RDB snapshot.

What is the difference between Redis Sentinel and Redis Cluster?

Sentinel adds monitoring and automatic failover to one primary that holds the whole dataset. Cluster shards the data across several primaries using 16,384 hash slots and handles failover itself. Use Sentinel while the data fits on one node, Cluster when it does not.

How is Valkey's architecture different from Redis?

The core is the same: Valkey forked Redis 7.2.4. Valkey 8.0 added its own asynchronous I/O threading and dual-channel replication, and Valkey 8.1 replaced the main key table with a new, more memory-efficient hash table. Commands still execute on one main thread.

Scott Sternloff

Author

Scott SternloffSenior Enterprise Architect

Senior Enterprise Architect at AceMQ. Writes the technical coverage here: RabbitMQ, Kafka and Redis architecture, clustering and migrations.

Talk to an engineer

Need a hand with Redis?

Senior engineers who run it in production. Get a quote or a free consultation, no sales pitch.

Free Consultation

Get Expert Eyes on Your Redis Deployment

Whether you're troubleshooting a production incident, planning a migration, or want a second opinion on your architecture — our team is ready. No pitch, just answers.

Email Us