Skip to content

The database recovered an hour ago. Why is the platform still down?

The Failure Should Have Stopped There · Part 6 of 6 · 6 min read

Read the worked explanation ↓

A reservation platform can usually complete 10,000 purchases/s. A transient outage causes 600,000 queued operations, clients retry and workers crash-loop. External traffic has returned to 8,000/s. Create a fifteen-minute stabilization plan, explicit entry and exit criteria, and a long-term design preventing recurrence.

Think first

A reservation platform can usually complete 10,000 purchases/s. A transient outage causes 600,000 queued operations, clients retry and workers crash-loop. External traffic has returned to 8,000/s. Create a fifteen-minute stabilization plan, explicit entry and exit criteria, and a long-term design preventing recurrence.

Take a few minutes to form an approach, then compare it with the worked explanation.

Reveal the worked explanation

Interview question. A ticketing platform suffered a ten-minute database slowdown during a ticket release. The database has been healthy for an hour and original customer traffic is back to normal, yet API success remains near zero. Queues, retries and restarted workers are now the dominant load. Diagnose a metastable failure and design a safe exit.

The incident timeline doesn't make sense if you expect every failure to end when its initial cause ends. At 14:00 database latency spikes. At 14:10 the storage team fixes the underlying problem. At 14:30 the platform still cannot process a normal purchase. Engineers add instances. They also see more timeouts. But the system may now be failing for a reason that no longer requires the database problem.

A metastable failure is a system state sustained by its own internal positive feedback. A temporary disturbance pushes the system out of a healthy operating region. Retries, retained backlog, cache misses, connection storms or repeated restarts keep it overloaded even after the original disturbance disappears. Research on metastable distributed-system failures describes how useful work can collapse and how returning to a previously safe external arrival rate may be insufficient for recovery. The key sign is hysteresis: what load the system can tolerate depends on the condition it is already in.

A temporary database slowdown moves the system from healthy throughput into a retry-and-backlog loop that persists until load is actively reduced.
A temporary database slowdown moves the system from healthy throughput into a retry-and-backlog loop that persists until load is actively reduced.

Start with counters that separate new customer demand from total attempted internal work. Suppose new user traffic is 8,000 operations per second. A retry loop adds 5,000 attempted operations per second, while delayed background tasks contribute another 4,000 expensive operations per second. The backend now sees 17,000 attempted operations per second against a healthy capacity of 10,000 for this simplified workload. Reporting only new inbound RPS makes the load appear safe when the actual work offered is not.

There is a second problem: queue age. Imagine 600,000 queued tasks accumulated during the disruption. At a sustained processing rate of 10,000 tasks/s with 8,000 new tasks/s, net drain would be 2,000 tasks/s and clearing the old backlog would take 300 seconds, assuming uniform task cost, no retries and no expirations. But if the retry and background traffic consumes the spare capacity, the backlog does not drain. Expired tasks may still occupy workers and database connections even though their customer deadlines passed.

Now look at worker restarts. A saturated process misses health checks, is killed, and restarts with empty caches and cold connection pools. Healthy throughput from that instance is initially lower than steady state. The load balancer sends pending work to it as soon as it appears ready, it becomes saturated again, and another restart follows. Replacing instances or autoscaling can paradoxically decrease the amount of useful work completed.

How do you recover? First protect the source of truth and prevent irreversible duplicate effects. Establish a trusted picture of accepted versus completed operations using durable IDs, authoritative order state and a clear cutoff for deadlines. Then sharply reduce offered work to a level the currently healthy capacity can sustain. Temporarily suspend optional imports, recommendations, search-index backfills and nonurgent batch tasks. Gate new purchases at admission, preferably before allocating expensive downstream resources. Disable or bound retry layers that are multiplying attempts. This may mean deliberately returning fast errors for some new requests to restore a smaller core of correct completions.

Recovery may need phases rather than one switch. Phase one: protect payments, ticket ownership and inventory invariants. Phase two: let the database, caches and workers warm under a small, controlled load. Phase three: process retained legitimate work at a rate below measured spare capacity. Phase four: ramp fresh traffic, watching whether useful completion rate increases without a renewed queue-age rise. Do not simply dump the backlog on the newly recovered database. If tasks are now meaningless or expired, apply an explicit audited expiry or cancellation policy rather than silently deleting them.

The word goodput matters. A process can report 20,000 handled requests per second while completing only 2,000 distinct customer operations because most handled requests are retries, short-lived probes or calls doomed by expired deadlines. Count successful unique purchases, valid state transitions and useful completed background work. Track duplicate-attempt ratio, oldest queue age, in-flight work, startup churn, database write cost and per-tier admission. The recovery graph should show not just lower CPU but rising useful completions and falling residual backlog.

This lesson differs from the earlier cascade. A cascading failure describes how distress spreads from one part of a service graph into others. A metastable failure asks why the broken state persists after the trigger vanishes. Both may involve retries, but the diagnostic test is different. For the metastable case you should be able to construct a timeline in which the original defect is demonstrably gone while feedback loops continue to suppress goodput. Simply identifying the first failing dependency is not enough.

The long-term fix should remove the vulnerable operating mode. Give every queue a purpose, capacity bound, age policy and admission signal. Use end-to-end deadlines and propagate cancellation so abandoned work does not continue invisibly. Cap retries globally, not just per SDK. Preserve spare resources needed for startup, credential refresh and control operations. Validate readiness using the ability to process real useful work, not merely answer /health. Design controls to reduce traffic quickly, including safety rails for reopening.

In the interview, I would not promise that the database returning healthy means the incident is over. I would ask, “What work is the system actually doing now, where did it come from, and can we lower that work long enough to recover useful throughput?” That moves incident response from chasing the original trigger to changing the state the system is trapped in.

Go deeper

Metastability can be modeled with arrival-dependent service rates and feedback-generated work. At a healthy state, effective service capacity may exceed fresh demand. As queues grow, cache efficiency drops and retry traffic increases, reducing effective useful throughput. This can create two operating regions for similar external rates. Restoration requires crossing a lower-load threshold, not merely returning to the old operating point. Avoid deriving precise thresholds from the simple 17,000-versus-10,000 calculation because real tasks have variable cost and the service capacity itself changes with state. Instead, infer safe recovery headroom experimentally, with abort conditions protecting data correctness.

Check your reasoning

  • Prove the original trigger ended while feedback from retries, queues and restarts remains.
  • Separate fresh arrivals, retry attempts, backlog work and successful unique outcomes.
  • Check 8k+5k+4k=17k attempted work/s and conditional 600k/(10k-8k)=300s backlog drain.
  • Design safe staged recovery preserving authoritative purchase and inventory state.
  • Use goodput and queue-age exit criteria plus long-term fault and recovery tests.

Common mistake: Once inbound user traffic falls below its prior healthy limit, a recovered database guarantees that the service stabilizes.

Which recovery plan can exit a feedback-sustained failure after the original database trigger is gone?

Read the answer explanation

Suppress optional work and retries, admit below current safe capacity, then drain and ramp using goodput evidence — Effective service capacity and offered internal work can change after overload. Reducing the original external arrival rate alone may not break the sustaining feedback.

Apply it elsewhere

A coding-agent fleet lost its model provider for five minutes. The provider recovers, but queued tool runs, expired agent turns and retrying SDKs keep GPU inference and sandbox capacity saturated. Apply a staged recovery that preserves accepted-work semantics.

Compare your approach

Separate original trigger from self-sustaining load, calculate total offered versus useful completed work, distinguish queue drain from backlog persistence, stage admission and retry reductions safely, and define metrics and tests proving an actual exit from the overloaded state.

One more constraint

If fresh demand returns below a system's previous healthy throughput, does that guarantee it will recover without actively reducing retries and backlog work?

Quick revision

Metastability means a temporary disturbance leaves behind feedback that sustains failure. Original traffic can return to normal while retries, expired queued work, cold starts and health-check restarts keep the system overloaded. Measure new demand separately from all attempted work, and goodput separately from raw requests. Recover by protecting authoritative state, suppressing optional work and retries, admitting less than current real capacity, draining legitimate backlog, and ramping gradually. The incident ends when useful completions recover and the feedback loop is broken.

References