Read path

94% of reads never touch the database

Redis answers them in about 1 ms. Only misses reach Postgres.

user-service · GET /user/:id · 7 days to 1 Oct

GET /user/42 get key hit · 1 ms miss: SELECT row · 9 ms set key Client APIuser-service RedisTTL 60 sno keyTTL 60 s Postgres
  1. The client asks the API for user 42.
  2. The API asks Redis first.
  3. A hit returns in about 1 ms. Done.
  4. A miss reads Postgres in about 9 ms, because the key expired.
  5. The API writes the row back, so the next read hits.
Fig. 1Each moving dot is one read. One in sixteen misses and goes on to Postgres.

Load

Postgres now serves 6% of reads

Hit rate · 7 days94% 6 misses
p50 read latency1.2 ms hit1 msmiss9 ms
Postgres reads / s340 before5.6know340
Fig. 2Each square is 1% of reads. A miss costs 9× a hit.

Failure modes

One failure mode is still open

Handled

User updates profile

API Rediskey deleted Postgresfresh row
Handled

Key reaches its TTL

API Redisexpired Postgresrefill
Accepted

Write races a read

API Redisold ≤ 60 s Postgresnew row
Open risk

Redis is down

API Redisdown Postgres16× load
Fig. 3Postgres cannot take the full read load if Redis fails.

Sources

src/cache/user.ts:14–52 · src/routes/user.ts:30 · dashboard "user-service read path", last 7 days.