Why Redis Is Fast

Don't just say that Redis is fast because it stores data in RAM. That explanation is incomplete.

1. An Engineering Question

A few months ago, we were building a feature that required retrieving configuration toggles and basic feature flags on almost every API call. This data was accessed frequently but updated rarely. To keep the retrievals fast, we set up a Redis instance to store these settings.

It worked exactly as expected. But after a few days, the engineering curiosity kicked in. I started questioning the setup:

  • Why did we need a separate tool like Redis?
  • Could we not have simply created a small, highly indexed table in our existing PostgreSQL database and queried that?
  • Why is making a database call to a small PostgreSQL table slower than querying Redis?
  • What makes Redis fundamentally faster than standard databases at a code and operating system level?

This question led me down a rabbit hole of database internals and operating system designs. It turned out that Redis's speed isn't a magic trick of 'running in RAM'—it is the result of continuous bottleneck removal at the system level. This article summarizes those architectural differences.

Before putting this article together, I spent a lot of hours digging into the source code and understanding the system-level details of Redis, debating extensively with ChatGPT on the trade-offs, thread dynamics, and CPU constraints. I have prepared this article as a crux and a summary of my key learnings from that deep dive.

2. Why Not Just a Database Table?

If you query a small, 100-row table in an indexed PostgreSQL database, the data is cached in PostgreSQL's shared buffers (RAM). Yet, that query still takes 1.5ms to 3ms, whereas Redis returns the same key in 0.2ms. Why?

The difference lies in the design goals. Relational databases are built for complex SQL queries, multi-table joins, ACID transactions, and disk-bound reliability. Even when data is fully loaded in memory, a query must still be parsed, optimized, and execute locks. Redis, by contrast, removes these layers. It trades relational query flexibility in exchange for direct memory lookup paths.

3. Bypassing the Disk

The first major optimization is the physical storage medium. Disk drives are slow, SSDs are faster, but main memory (RAM) is in a completely different league. To put this in perspective: if accessing the CPU L1 cache is like grabbing a coffee on your desk, accessing RAM is like walking down the street to a café. Fetching data from an SSD? That is like booking a flight to another city. And a spinning HDD? That is a journey around the world.

Let's look at the storage hierarchy latencies:

Storage Hierarchy Latency Relative Visual Scale
CPU L1 Cache ~0.5 - 1 ns Instantaneous
RAM (Main Memory) ~100 ns 100x slower than L1
NVMe SSD ~100,000 ns (100 μs) 100,000x slower than L1
Spinning HDD ~10,000,000 ns (10 ms) 10,000,000x slower than L1

Interactive Storage Latency Simulator

Click a storage medium below to trigger a query request. The simulator visualizes the physical time latency difference (scaled down for visualization) in fetching data.

Database RAM/Disk
Speed: -
Time Taken: -

By keeping all active data directly in RAM, Redis avoids the slow disk read path. Writes and reads are pointer offsets in memory—not physical disk seeks or cache page swaps.

Engineering Trade-off: Memory is volatile and expensive. A system storing 1 TB of data in RAM costs significantly more than one storing 1 TB on SSDs. Redis accepts this cost trade-off to prioritize speed.

4. Algorithmic Efficiency

How data is represented in memory dictates how many CPU cycles are spent looking it up. Relational databases use search trees (like B+ Trees or LSM-Trees) to navigate data pages. Redis uses a global HashTable where every key maps directly to a value, providing O(1) lookups.

Additionally, Redis is not just a basic key-value string store. It exposes rich, in-memory structures like Hashes, Lists, Sets, and Sorted Sets. Each structure is implemented with extreme care. Take Redis Strings, for example: they do not use standard null-terminated C strings. Instead, they use a custom representation called Simple Dynamic Strings (SDS). The SDS header stores the string length, which means checking string length is O(1) instead of O(N), and appends are memory-safe.

Data Structures Explorer

Redis uses specific data structures optimized for speed. Click a card below to explore how it is represented internally and its primary O-notation operations.

Strings

O(1)

Hashes

O(1)

Lists

O(N)

Sets

O(1)

Sorted Sets

O(log N)

Strings

Internal Implementation: SDS (Simple Dynamic String) - a custom string wrapper that stores length in metadata, enabling O(1) length checks and preventing buffer overflows.

Common Commands: GET, SET, INCR Primary Use: Sessions, Caching, Counters

5. Zero SQL Compiler Overhead

In a standard SQL database, a query string has to pass through a massive pipeline: parsing the SQL text, compiling an Abstract Syntax Tree (AST), checking schemas and permissions, running the query optimizer, selecting indices, and executing the plan.

When you run GET user:42 in Redis, there's no parsing engine or query planner. The protocol maps the `GET` command directly to a C function pointer, hashes the key, and retrieves the data from memory. By keeping it simple, Redis saves crucial CPU cycles.

Query Pipeline Visualizer

Click "Animate Pipeline" to compare the execution steps of a PostgreSQL query versus a Redis lookup.

Traditional SQL Database
1. Parse SQL String
2. Build AST Tree
3. Validate Schema Catalog
4. Run Query Optimizer
5. Select Execution Plan
6. Traverse B+ Tree Index
7. Fetch Page from Disk
Redis In-Memory Key-Value
1. Parse Command Text
2. Map to C Function Pointer
3. Hash Key & Lookup in RAM

6. The Concurrency Paradox

One of the most counter-intuitive decisions in Redis is its single-threaded execution model. Beginners often ask, "How can a single thread be faster than my multi-core CPU?" The answer lies in the cost of concurrency. Multi-threaded systems spend a massive amount of CPU cycles on thread scheduling, context switching, cache line invalidations, and lock contention. When two threads try to update the same memory block, one has to wait. Redis avoids all of this by processing client commands sequentially on a single thread. No locks, no context switches, and no race conditions. It's simple, predictable, and incredibly fast.

Multi-Threaded Locking vs. Redis Single-Threaded Event Loop

Start the simulation to compare how commands are processed. Notice how multi-threading requires locks and causes wait states, while Redis handles requests sequentially and smoothly.

Multi-Threaded (Locks & Contention)
Redis Single Thread (Sequential Event Loop)
Clarification: Redis is not entirely single-threaded. While the main command execution loop runs on one thread, background threads handle asynchronous tasks like disk syncing, socket writes, and cleaning memory pages.

7. Multiplexing Network I/O

But how does a single thread handle 50,000 active connections at once? If we spawned a thread for every client connection (the classic thread-per-connection model), the OS scheduler would fall over. Redis solves this with non-blocking I/O multiplexing. Under the hood, it leverages OS-specific mechanisms like epoll on Linux or kqueue on macOS. The single main thread monitors thousands of network sockets. When data is ready on a socket, an event triggers, and Redis processes it immediately. This event-driven loop keeps memory usage low and ensures that connection scaling doesn't hurt performance.

8. Decoupling Disk Writes

What happens if the power goes out? If Redis kept everything in memory without writing to disk, it would be a volatile cache, not a database. But disk writes are slow. To preserve its sub-millisecond latencies, Redis doesn't block client writes while writing to disk. Instead, it decouples persistence. You can configure it to take periodic binary snapshots (RDB) or log write commands in the background (AOF). These persistence tasks run on fork-created background processes, leaving the main execution thread free to serve clients.

Interactive Persistence Configurator

Click on a persistence model to inspect its latency impact and data durability trade-offs.

Memory Only (No Persistence)

Latency:
~0.1ms (Lowest)
Durability:
Volatile (Data lost on reboot)

All writes are kept purely in RAM. There is zero disk I/O overhead, providing maximum database throughput.

9. Architectural Matrix

By layering these optimizations together, Redis systematically removes latency at every level of the query pipeline. Here is the architectural summary of traditional databases versus the Redis approach:

Traditional Database Bottleneck Redis Architecture Solution
Disk Storage Read/Write latency RAM Main Memory Storage
SQL Parsing & Query Optimization overhead Direct command key-lookup mapping
Logarithmic search traversals (B-Trees) Constant-time Hash Tables & Skip lists
Thread scheduling & Lock synchronization Single-threaded Sequential Event Loop
Thread-per-connection limit overhead Non-blocking Socket I/O Multiplexing (epoll)
Synchronous Write-Ahead disk logs Asynchronous background thread snapshots (RDB/AOF)

10. Latency Benchmarks

To put this in perspective, here is a latency comparison for a simple key query under identical hardware constraints:

Comparative Latency Benchmarks

Hover over the bars below to see the average query latencies in milliseconds.

0.3 ms
Redis GET
2.0 ms
PostgreSQL Lookup
3.0 ms
MySQL Lookup

Note: Benchmarks reflect indexed key lookups. Actual performance varies based on hardware, indices, network conditions, and payload size.

11. When Redis Isn't Fast

Redis is not a silver bullet. Its speed degrades under specific workloads:

O(N) Complex Operations

Commands like KEYS *, SINTER, or fetching massive sorted sets block the single thread, queuing all incoming requests.

Exceeding Available memory

When the dataset size exceeds available RAM, the OS forces swap pages to disk, reducing performance instantly.

Strong ACID Requirements

Configuring AOF with `fsync always` forces a disk write on every command, reducing performance to standard disk bounds.

12. Key Takeaways

The core lesson of Redis is that high performance is rarely achieved by a single optimization. Instead, it is the result of continuous bottleneck elimination: storing data in RAM exposed network bottlenecks, solved by epoll; which exposed lock contention bottlenecks, solved by single-threading; which exposed disk-write bottlenecks, solved by background persistence.

Apply this compounding optimization mindset to your own distributed systems, APIs, and front-end architectures.


Swastik Kumar

Written by Swastik Kumar

I'm a Full Stack Software Engineer focused on backend systems and database internals. Over the last two years, I've worked on high-throughput backend services, including payment flow module, hotel indexing and searching, document management system enabled with OCR.