IncidentPaged 12:00 UTC (deploy window), Monday
post-deploy thundering herd: 8 pods restart, Postgres replica panics
Service: catalog-api (FastAPI + Redis cache, Postgres read replica behind)
Symptom: Every rolling deploy produces a 30-second window of 5xx responses and replica connection-pool saturation. Steady state is fine — the burn is exactly around the deploy. Ops bookmarked the graph.
The code that's running in prod
# catalog/products.py
from fastapi import FastAPI
import redis.asyncio as redis
import asyncpg
import json
app = FastAPI()
cache = redis.Redis(host="cache", decode_responses=True)
pool: asyncpg.Pool # initialised on startup
@app.get("/products/{product_id}")
async def get_product(product_id: int):
cached = await cache.get(f"product:{product_id}")
if cached is not None:
return json.loads(cached)
# Cache miss — read through to Postgres.
async with pool.acquire() as conn:
row = await conn.fetchrow(
"SELECT id, name, price_cents, stock FROM products WHERE id = $1",
product_id,
)
payload = dict(row)
await cache.set(f"product:{product_id}", json.dumps(payload), ex=300)
return payload
Log dashboard (last 60 seconds)
Pick the root cause
Four candidates. Three are plausible but mistake symptom for cause. Pick what you'd write in the postmortem timeline.