redis/redis
For developers, who are building real-time data-driven applications, Redis is the preferred, fastest, and most feature-rich cache, data structure server, and document and vector query engine.
12 hidden assumptions · 9-stage pipeline · 8 components
Like any codebase, this repository makes assumptions it never checks — most are routine. The ones worth your attention are below.
Stores and retrieves data structures in memory with persistence and networking
Data enters Redis through TCP client connections as command strings, gets parsed into command arguments, validated and executed against in-memory data structures, with responses sent back to clients. Background processes periodically persist data to disk via RDB snapshots or AOF logging, while expired keys are actively and passively cleaned up.
Under the hood, the system uses 4 feedback loops, 5 data pools, 5 control points to manage its runtime behavior.
A 8-component repository. 811 files analyzed. Data flows through 9 distinct pipeline stages.
Hidden Assumptions
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
If the event loop is destroyed while async Redis operations are pending, the adapter will attempt to use freed memory, causing crashes or memory corruption
Race condition where the main context is accessed after the source is destroyed, leading to use-after-free crashes in the GLib event loop
In multi-threaded environments, concurrent histogram updates could corrupt the normalization calculation, leading to incorrect bucket indexing and data corruption
Show everything (9 more)
Assumes the counts array length (counts_len) matches the allocated size of the counts pointer, but the struct provides no built-in bounds checking
If this fails: Buffer overflows when accessing counts[index] if the array was resized without updating counts_len, leading to memory corruption or crashes
deps/hdr_histogram/hdr_histogram.h:hdr_histogram
Assumes 64-bit integers are naturally aligned on the target platform, relying only on compiler barriers rather than hardware-specific atomic operations
If this fails: On platforms where 64-bit loads aren't atomic (like 32-bit x86), torn reads could return partially updated values, corrupting histogram statistics
deps/hdr_histogram/hdr_atomic.h:hdr_atomic_load_64
Assumes Redis's zmalloc/zfree functions are compatible with standard malloc/free semantics and handle NULL pointers correctly
If this fails: If zmalloc has different behavior than standard malloc (like returning different error codes or handling alignment differently), histogram allocation could fail silently or corrupt memory
deps/hdr_histogram/hdr_redis_malloc.h:zmalloc
Assumes the iv_fd structure remains valid between the time it's configured with iv_fd_set_handler_in and when the ivykis event loop processes the event
If this fails: If the redisIvykisEvents structure is freed before ivykis processes pending events, the event handler will be called with a dangling pointer, causing crashes
deps/hiredis/adapters/ivykis.h:redisIvykisAddRead
Assumes the libev event loop and the Redis async context have synchronized lifetimes, with no mechanism to handle cases where one is destroyed before the other
If this fails: Dangling pointers between the libev watchers and Redis context, potentially causing callbacks to be invoked on freed memory
deps/hiredis/adapters/libev.h:redisLibevEvents
Assumes significant_figures parameter is between 1 and 5, but the histogram constructor may not validate this range
If this fails: Values outside this range could cause integer overflow in bucket calculations or create histograms with unexpected memory usage patterns
deps/hdr_histogram/hdr_histogram.h:significant_figures
Assumes the platform's stdint.h provides exactly the same integer types as expected by the Grisu algorithm's bit manipulation
If this fails: On exotic platforms with different integer representations, the floating-point conversion could produce incorrect decimal strings
deps/fpconv/fpconv_powers.h:stdint.h
Assumes GLib's poll event constants (G_IO_IN, G_IO_OUT) map correctly to the underlying system's poll/epoll constants
If this fails: Incorrect event monitoring if GLib's constants don't match system expectations, leading to missed read/write readiness events
deps/hiredis/adapters/glib.h:G_IO_IN
Assumes compiler memory barriers (_ReadBarrier, _WriteBarrier) provide sufficient ordering guarantees for atomic operations without hardware memory barriers
If this fails: On weakly-ordered architectures, the CPU might reorder memory operations despite compiler barriers, leading to race conditions in histogram updates
deps/hdr_histogram/hdr_atomic.h:_ReadBarrier
Open the standalone hidden-assumptions report for redis →
How Data Flows Through the System
Data enters Redis through TCP client connections as command strings, gets parsed into command arguments, validated and executed against in-memory data structures, with responses sent back to clients. Background processes periodically persist data to disk via RDB snapshots or AOF logging, while expired keys are actively and passively cleaned up.
- Accept client connection — The event loop calls acceptTcpHandler when new TCP connections arrive, creating a client struct and adding the socket to the event loop for read events
- Read query buffer — readQueryFromClient reads incoming bytes into client->querybuf (sds string), accumulating partial commands until complete RESP protocol messages are received [client → client]
- Parse commands — processInputBuffer parses the query buffer into argc/argv format, splitting RESP arrays into individual string arguments and storing them as robj pointers in client->argv [client → client]
- Execute command — processCommand looks up the command in the command table, validates permissions and argument count, then calls the command's proc function (like setCommand, getCommand) with the client context [client → redisObject]
- Modify data structures — Command handlers like setCommand call dbAdd/dbOverwrite to store robj values in the database dict, while getCommand calls lookupKey to retrieve values, with all operations going through the redisDb hash tables [redisObject → redisObject]
- Generate response — Command handlers call addReply functions to build RESP protocol responses in client->reply list, with responses like +OK, -ERR messages, or bulk string data [redisObject → client]
- Send response — sendReplyToClient writes accumulated response data from client->reply to the TCP socket during writable events, handling partial writes and flow control [client]
- Persist to AOF — propagate calls feedAppendOnlyFile for write commands, serializing the command and arguments to the AOF file for durability and replication [redisCommand]
- Create RDB snapshot — rdbSaveBackground forks a child process that calls rdbSave to iterate through all databases and serialize every key-value pair to a binary RDB file [redisDb]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
src/server.hC struct with type: unsigned (4 bits), encoding: unsigned (4 bits), lru: unsigned (24 bits), refcount: int, ptr: void* — the universal container for all Redis values
Created when data enters Redis, reference-counted during operations, freed when no longer referenced or during eviction
src/server.hC struct with fd: int, db: redisDb*, querybuf: sds, argc: int, argv: robj**, reply: list*, authenticated: int — represents a connected client session
Created on TCP connection, accumulates query buffer and parsed commands, destroyed on disconnect
src/server.hC struct with dict: dict*, expires: dict*, blocking_keys: dict*, id: int — represents a Redis database (0-15 by default)
Initialized at server startup, persists throughout server lifetime, cleared during FLUSHDB
src/server.hC struct with name: char*, proc: function pointer, arity: int, sflags: char*, flags: int — defines a Redis command's metadata and handler
Statically defined at compile time, registered during server initialization, immutable during runtime
src/server.htypedef of redisObject — the standard Redis value container with type, encoding, and data pointer
Created for every value stored in Redis, persisted until expired or evicted, serialized during RDB/AOF operations
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Hash tables storing all Redis keys and values in memory with optional expiration timestamps
Per-client response queues that accumulate reply data before sending to TCP socket
Append-only log file storing write commands for persistence and replication
Binary snapshot file containing complete dataset state at point-in-time
Hash table mapping module names to loaded module instances with their commands and types
Feedback Loops
- Client backpressure (backpressure, balancing) — Trigger: Client output buffer exceeds limits. Action: Pause command processing and close slow clients. Exit: Buffer size returns to normal.
- Memory eviction (auto-scale, balancing) — Trigger: Memory usage exceeds maxmemory limit. Action: Evict keys using LRU/LFU algorithms until under threshold. Exit: Memory usage drops below limit.
- AOF rewrite (self-correction, balancing) — Trigger: AOF file size exceeds configured growth threshold. Action: Fork background process to rewrite AOF with minimal command set. Exit: New AOF file replaces old one.
- Expired key cleanup (polling, balancing) — Trigger: Timer events or key access. Action: Randomly sample keys with TTL and delete expired ones. Exit: Continuous background process.
Delays
- RDB background save (async-processing, ~Seconds to minutes depending on dataset size) — Child process serializes data while parent continues serving clients
- AOF fsync (eventual-consistency, ~System-dependent disk sync time) — Write commands may be lost if system crashes before fsync completes
- Client timeout (cache-ttl, ~Configurable client-timeout seconds) — Idle clients are closed to free resources
- Key expiration (cache-ttl, ~Per-key TTL values) — Keys become inaccessible after expiration time passes
Control Points
- maxmemory (threshold) — Controls: Memory usage limit that triggers eviction policies
- save configuration (threshold) — Controls: RDB save intervals based on time and number of changes
- appendonly (feature-flag) — Controls: Whether AOF persistence is enabled
- timeout (threshold) — Controls: Client idle timeout before automatic disconnection
- tcp-keepalive (threshold) — Controls: TCP keepalive interval for detecting dead clients
Technology Stack
High-performance memory allocator optimized for multi-threaded applications, used as default allocator in Redis
Embedded scripting engine for executing atomic scripts on Redis server side
C client library providing both synchronous and asynchronous APIs for Redis communication
Lightweight readline replacement for redis-cli command line editing and history
High dynamic range histogram for latency tracking and performance monitoring
Key Components
- aeEventLoop (orchestrator) — Core event loop that coordinates I/O events, time events, and before-sleep hooks using epoll/kqueue/select
src/ae.c - processCommand (processor) — Central command processor that validates, authenticates, and dispatches Redis commands to their specific handlers
src/server.c - dictCreate (factory) — Creates hash table instances used throughout Redis for key storage, client tracking, and internal data structures
src/dict.c - rdbSave (serializer) — Serializes the entire Redis dataset to a binary RDB file for persistence and replication
src/rdb.c - aofRewrite (serializer) — Reconstructs AOF file by generating minimal command sequence to recreate current dataset state
src/aof.c - redisAsyncContext (adapter) — Manages asynchronous Redis client connections with callback-based command execution and event loop integration
deps/hiredis/async.c - moduleLoadFromQueue (loader) — Dynamically loads Redis modules from shared libraries, registering their commands and data types with the server
src/module.c - zmalloc (allocator) — Memory allocation wrapper that tracks Redis memory usage and integrates with jemalloc for optimized memory management
src/zmalloc.c
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Repository Repositories
Frequently Asked Questions
What is redis used for?
Stores and retrieves data structures in memory with persistence and networking redis/redis is a 8-component repository written in C. Data flows through 9 distinct pipeline stages. The codebase contains 811 files.
How is redis architected?
redis is organized into 5 architecture layers: Core Server, Data Types Engine, Persistence Layer, Client Libraries, and 1 more. Data flows through 9 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through redis?
Data moves through 9 stages: Accept client connection → Read query buffer → Parse commands → Execute command → Modify data structures → .... Data enters Redis through TCP client connections as command strings, gets parsed into command arguments, validated and executed against in-memory data structures, with responses sent back to clients. Background processes periodically persist data to disk via RDB snapshots or AOF logging, while expired keys are actively and passively cleaned up. This pipeline design reflects a complex multi-stage processing system.
What technologies does redis use?
The core stack includes jemalloc (High-performance memory allocator optimized for multi-threaded applications, used as default allocator in Redis), Lua (Embedded scripting engine for executing atomic scripts on Redis server side), hiredis (C client library providing both synchronous and asynchronous APIs for Redis communication), linenoise (Lightweight readline replacement for redis-cli command line editing and history), hdr_histogram (High dynamic range histogram for latency tracking and performance monitoring). A focused set of dependencies that keeps the build manageable.
What system dynamics does redis have?
redis exhibits 5 data pools (Main database, Client output buffers), 4 feedback loops, 5 control points, 4 delays. The feedback loops handle backpressure and auto-scale. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does redis use?
5 design patterns detected: Event-driven architecture, Reference counting, Copy-on-write persistence, Plugin architecture, Protocol abstraction.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.