02:14:07 upstream timed out (110: Connection timed out)
02:14:09 pool-1 — connection is not available, request timed out after 30000ms
02:14:11 GET /api/checkout/session → 504 · p95 30s
In plain language. An error, a log extract, a screenshot — whatever you already have in front of you.
$ grep -n "pool" gateway-2026-09-03.log | tail
14:07 retry_handler: attempt 2 → opening connection
14:07 retry_handler: attempt 3 → opening connection
14:09 pool exhausted — 20/20 held, oldest 4m12s, none returned
14:09 checkout.session → waiting … timeout(30s) → 504
Logs read, config diffed, the failure reproduced. What you get back is the cause — not the first plausible-sounding answer.
What it will take, what it will cost, and what happens if it turns out to be bigger than it looked. Then you decide.
gateway/retry.py
- conn = pool.getconn() # opened per attempt, never returned
+ with pool.connection() as conn: # returned even when the attempt raises
+ ... # and the retry is safe to run twice
alerts/pool.yml · new: pool_in_use > 80% for 2m → page
The work is done, handed back, and explained. The explanation is the part that stops it happening again.
Fixed 1920×1080, scaled to fit — a screen recording of the frame is pixel‑exact. Controls sit outside the frame. Space = play/pause, R = replay, 1–6 = jump to an act.