It is the World Cup final. In the last minute of the game, 500,000 users refresh their applications at almost the same moment.
Every request triggers a simple query:
SELECT score
FROM matches
WHERE id = '00000000';The data is already in RAM, but that is not the whole story. A huge number of requests arrive at the database layer within a very short time.
The database handles those requests through workers, usually processes or threads. At any moment, only a limited number of workers can actually execute on the available CPU cores.
Databases can respond to this pressure in several ways, each with its own operational cost and complexity:
1. Read replicas can distribute read traffic, but they add replication, routing, consistency, and operational concerns.
2. Connection pooling can reduce connection overhead, but it cannot make unlimited queries execute simultaneously.
3. Application-level micro-caching can collapse repeated requests, but it introduces expiration and invalidation decisions.
Now consider the shared page in the database buffer pool. Multiple workers can read the same page, but the page is not just an unstructured sequence of bytes. The database also maintains shared metadata about the buffer that contains it.
That metadata can include whether the buffer is valid, whether it can be reused, and how many workers currently depend on the page. A buffer pin is a reference count: a worker pins the buffer while it needs the page and releases the pin when it is finished. This helps prevent the page from being evicted or reused while it is still in use.
Why must the database coordinate this metadata if the operation is only a read? Because the read path still changes shared state. Finding the page is logically a read of the data, but pinning and unpinning the buffer update the buffer’s metadata.
The simplified sequence looks like this:
- Locate the buffer containing the page.
- Safely update shared metadata and increment the pin count.
- Read the page contents.
- Safely update the metadata again and decrement the pin count.
The synchronization used to protect short critical sections around shared database state is commonly described as a latch. A latch is not the same thing as a buffer pin: the pin expresses that a worker is using a buffer, while the latch or related synchronization protects metadata while it is being changed.
Before a worker can safely use a shared page, it may need to coordinate briefly with other workers touching the same shared memory state. The critical section may be very short, but those short waits can accumulate when a large number of workers target the same hot page or buffer.
Back to the World Cup example:
- Many workers may contend for the same shared buffer metadata.
- They must coordinate metadata updates, access the data, and release their references safely.
- Fewer workers make progress while others wait, increasing tail latency.
- CPU time can be spent coordinating access to shared state instead of serving the requested value.
This is latch contention: the bottleneck is not necessarily retrieving the bytes from RAM, but coordinating many concurrent workers around shared database structures. CPU usage can become very high even when the query itself appears simple.
So what can Redis do differently? For a single Redis instance, command execution is normally serialized on one main event loop: one command runs at a time on that execution path. This avoids having multiple command workers simultaneously modify the same key-value data structures, so the application does not face PostgreSQL-style buffer-page and MVCC coordination for a simple key lookup.
That does not mean Redis has no concurrency or synchronization anywhere. Redis can use background threads for tasks such as persistence and may use I/O threads in some configurations. Replicas and Redis Cluster also introduce their own coordination and consistency considerations. The narrower point is that simple commands on one Redis execution path avoid the same per-query shared buffer contention model.
So does single-threaded execution always beat multi-threaded execution? No. It can be extremely effective when commands are small, predictable, and fast, because it removes lock contention and context-switching overhead. But one long-running command can block other commands on that execution path, and a single instance is ultimately limited by the work one execution thread can perform.
Redis is fast here because it uses a simpler data model and a simpler execution path for this workload. The trade-off is that PostgreSQL provides a much broader set of guarantees and capabilities, while Redis is best used as a carefully designed accelerator rather than a universal replacement.

