Cruxly

Cruxly › System design › Principles of Distributed Design

Failure Is a Mode, Not an Exception

for every dependency, the question is what the system does when it's down — not whether it can be

Open the interactive lesson

The principle: in a system of enough components, something is always failing. Treating failure as an exceptional branch produces designs that are correct on the happy path and undefined everywhere else. For every dependency, specify the behaviour when it is unavailable — that behaviour is a designed feature, not an error case.

The reframing is the whole principle: "the cache is down" is not an incident to be handled later, it is a mode the system operates in, and someone decides what that mode looks like. If you do not decide, it gets decided by whatever the code happens to do.

The violation: a design that only describes the happy path

Request → Auth service → Cache → Database → Response

Ask of each hop: and if this one is down? A design that has not answered acquires its behaviour by accident:

The cache case deserves particular attention, because it is the most common way a small failure becomes a large one. A cache is usually justified as a latency optimisation, which makes it feel optional — but once the database is provisioned assuming the cache absorbs most reads, the cache is load-bearing. Losing it does not make the system slower; it makes the system dead.

The fix: name the mode, and choose it deliberately

For each dependency, write down the degraded behaviour as a decision:

Auth down      → fail CLOSED. Reject requests. (Serving data to
                 unauthenticated users is worse than serving nothing.)

Cache down     → serve from DB, but with a concurrency limit + load shedding,
                 so the DB receives survivable load and sheds the rest
                 rather than collapsing under all of it.

Database down  → serve stale cached reads where correctness permits;
                 reject writes with a clear error. Reads degrade, writes stop.

Payment provider
     unreachable → do NOT guess. Leave the transaction PENDING and
                 reconcile from the provider's own record afterwards.

:::key The sentence that distinguishes a senior answer Not "we'd add a circuit breaker" — a mechanism — but "when the recommendation service is down we render the page without recommendations, because the page is still useful and the alternative is losing the whole page for a non-essential module." The mechanism follows from the decision; naming only the mechanism skips the part that was actually hard. :::

Timeouts, retries, and the failure the fix creates

Two mechanisms follow directly from this principle, and both cause outages when applied naively.

The general lesson underneath both: the fix for a failure mode introduces its own failure mode.

How to say it in the interview

"For each dependency here I want to say what happens when it is unavailable, because at this number of components something is always down — so 'the payment provider is unreachable' is a state this system spends real time in, and I would rather design that state than discover it."

Checklist

Practice this interactively
Share this lessonWhatsAppLinkedInX

Related lessons