Why Redis? Let’s start with a simple question: how quickly can a system access data at different layers of the memory and storage hierarchy?
The following latency figures are approximate and depend on the hardware and workload, but they show the scale of the difference:
L1 CPU cache: 0.5 ns
RAM: 100 ns (0.0001 ms)
SSD: 100,000 ns (0.1 ms)
HDD: 10,000,000 ns (10 ms)RAM access can therefore be roughly 1,000 to 100,000 times faster than storage access, depending on which storage device and access pattern we compare.
If we care about fast data access, databases already have caches, right? Yes, databases do cache data, but that does not make the database itself disappear from the request path.
For example, PostgreSQL commonly involves two relevant caching layers:
- Shared Buffers: PostgreSQL’s own memory cache. It stores database pages, usually 8 KB blocks, rather than individual rows or objects. If you need one 200-byte row, the cached unit is still the page containing it.
- The operating system page cache: the OS may also cache filesystem data, commonly in 4 KB pages. PostgreSQL does not have complete control over this cache because the kernel manages it and may evict data when memory is needed elsewhere.
This creates our first problem: the database may cache more data than the application needs, consuming memory, while the application does not fully control what remains in the OS cache. Data that was hot can be evicted when the operating system needs that memory for another purpose.
Problem 2: even if the required database page is already cached, what happens when the application runs a query such as this?
SELECT my_perfect_cached_data
FROM table
WHERE id = 'abc';The row may already be in memory, but the database still has work to do:
- It parses the query and validates its syntax, which requires CPU time.
- It plans the query and chooses an access path, such as an index scan or another plan. Databases can reuse prepared plans in some cases, but planning is still part of the database machinery when a plan is needed.
- It applies the relevant concurrency and visibility rules. A normal PostgreSQL read does not usually take a blocking row lock, because PostgreSQL uses MVCC, but it still performs transaction and visibility checks.
- It traverses an index, when one is used, to find the page containing the row.
- It works with the whole database page, even when the application needs only a small part of one row.
- It interprets the page structure and extracts the requested row.
- Finally, it converts the result into PostgreSQL’s wire format before sending it to the application.
Some of this work can be optimized, but it cannot be eliminated completely while using a full relational database. It is part of what gives PostgreSQL transactions, consistency, query flexibility, and durability.
So what if we owned a separate tool that could do two things?
- Act as a fast cache for the small set of data the application reads constantly.
- Bypass the relational database machinery for those carefully selected hot paths.
That tool exists. It is called Redis.
This is not an argument for replacing PostgreSQL. High-scale applications often use Redis alongside a primary database: PostgreSQL remains the source of truth, while Redis serves frequently accessed, temporary, or derived data with very low latency.
The important design question is not “Should I put everything in Redis?” It is “Which data is hot enough, stable enough, and safe enough to cache, and how will the application handle expiration, invalidation, misses, and stale values?”

