valha

Checkout outage traced to one connection pool

published via claudeJun 19, 20262 min read

Checkout was down for 47 minutes on June 18 because one deploy halved the payment-service connection pool while doubling its connection hold time. Every other system stayed green, which is exactly why it took 22 minutes to find. The fix is a config guard, not a heroic rewrite.

Source 1Grafana, checkout golden signals, 2026-06-18Source 2PagerDuty incident #4211 timeline

Time to recovery
47 min
SLO budget: 43 min / quarter
Failed checkouts
3,120
GMV delayed
$86k
recovered within 24h
Alert to root cause
22 min
p50 last 5 incidents: 14

Source 1Source 2

The shape of the outage

Checkout errors went from 0.6% to 14% inside eight minutes of the deploy while the platform-wide rate never left its baseline. A failure this local to one service, this correlated with one deploy, should have taken minutes to attribute. The divergence between the two lines is the entire diagnosis.

Checkout failed alone, the platform line never moved

5xx rate by surface, % of requests, June 18

View source data
tCheckoutAll other traffic
13:500.40.3
14:000.60.3
14:109.80.4
14:2014.20.5
14:3011.60.4
14:401.10.3
14:500.50.3
source: Grafana checkout golden signals, 2026-06-18

Source 1

Timeline

Detection was fast; attribution was not. The 13 minutes between the page and the pool discovery were spent ruling out the usual suspects on dashboards that were, correctly, all green.

TimeEventState
14:02deploy 2026.6.18-3 ships payment-service v241healthy
14:07checkout error rate crosses 2%, first alert firesdegraded
14:11on-call paged; platform dashboards green, checkout reddegraded
14:24pgbouncer pool for checkout identified at 100% saturationdown
14:31deploy rolled back; pool drains in four minutesdegraded
14:49error rate back under SLO; incident closedhealthy

Source 2

The moment it surfaced

The root cause did not come from a dashboard. It came from asking why the database looked idle while checkout was starving. The answer was in pgbouncer, one layer above every graph we were staring at.

Marion (on-call)

DB CPU is at 30%, no lock pileup, no slow queries. Why is checkout timing out against an idle database?

assistant

Because it never reaches the database. The pgbouncer pool for checkout is pinned at 100/100 connections since 14:02: v241 halved the pool to 100 and doubled hold time by moving payment capture inside the transaction. Requests are queueing at the pooler, not the DB.

Marion (on-call)

So the DB graphs were always going to be green. Rolling back.

Source 2

What we ruled out

Traffic was flat: no spike, no bot surge, checkout volume within 4% of the previous Tuesday. The database was healthy the entire time: CPU under 35%, zero lock contention, p99 query time unchanged. And it was not a bad payment provider, whose latency held at baseline before, during, and after. Three green systems, one saturated pooler between them.

Traffic

Flat. Checkout volume within 4% of the previous Tuesday, no bot surge, no campaign.

Database

Idle. CPU under 35%, zero lock contention, p99 query time unchanged through the whole window.

Payment provider

Healthy. Latency at baseline before, during, and after; every call that reached it succeeded.

The canary ran at 5% traffic for ten minutes. Pool saturation is a function of concurrent held connections, not error rate, so at 5% of load the halved pool never filled, so the canary saw a healthy service and promoted.

pgbouncer saturation was tracked but never alerted: the metric predates the alerting migration and the port was missed. The dashboard existed; nobody was looking at it, because nothing had ever pointed there.

Source 1

Evidence trail

Everything below is linked for the next reader: the RCA carries the full connection-math walkthrough, the diff shows the two config lines that did it.

rca-checkout-2026-06-18.pdfFull RCA · 9 pages · connection math in §3
pdf

Source 2

Action items

  1. Platform ships the pool-size deploy guard, blocking any config lowering a pool below trailing 7-day peak concurrency (owner: Iris, June 27).
  2. Alert on pgbouncer pool saturation above 80% for five minutes, paging the owning service, not platform (owner: Marion, June 24).
  3. Canary stage gains a concurrency-proportional check so pool-class regressions surface at 5% traffic (owner: Théo, July 4).
  4. Payment capture moves back out of the transaction; hold time returns to the v240 baseline (owner: pay team, June 25).

Sources

  1. 1
    Grafana, checkout golden signals, 2026-06-18

    https://grafana.example.com/d/checkout

    cited in The shape of the outage · What we ruled out

  2. 2
    PagerDuty incident #4211 timeline

    https://example.pagerduty.com/incidents/4211

    cited in Timeline · The moment it surfaced · Evidence trail