Distributed Failure Catalogue
Purpose
Turn a symptom into a name, and a name into the skill that owns the fix. Distributed failures
recur in a small number of shapes; an engineer who can name the shape reaches the right
mechanism in minutes instead of rediscovering it during an incident.
This skill deliberately does not teach the fixes. Every entry ends at an owner, because a
catalogue that also explained the remedies would drift out of step with the skills that own
them. Destructive cleanup is the explicit exception, with bounded guard guidance below.
Its value is recognition and routing — and, for a design review, a list of concrete
failures to argue a design against rather than a general appeal to robustness.
Workflow
This is a protocol/operations catalogue, with no Java language minimum. The scheduled-task
reference uses the Java 25 API documentation for a long-standing contract. Inspect the target
runtime, scheduler/framework, client retry defaults and deployment configuration before
applying version-sensitive claims; this skill does not authorize upgrades or fault injection.
- Write down the observation, not the theory. "Inbound rate rose while success rate
fell", "the queue is empty and no alert fired", "duplicates 1.5 s apart". The index below
is keyed on observations.
- Build a shared timeline and denominator. Record clock domains, timestamp uncertainty
and sampling gaps; do not infer causal ordering from cross-host timestamps alone. Align deploys, topology changes, retries,
offered load, admissions, attempts, goodput, saturation and freshness. Rates without
logical-request/attempt denominators routinely misidentify amplification.
- Match the recognition index, then read the full entry and try to falsify the mechanism.
Several patterns share a symptom; require its discriminator and a competing explanation.
- Check "where it hides" in code, config, sidecars, SDKs and control planes before accepting the match.
A pattern you cannot locate in the system is a hypothesis, not a diagnosis.
- Go to the owner skill for the fix. Do not improvise a remedy from the entry — the
entries are deliberately too short to implement from.
- In a design review, walk the index as a checklist and require an answer for each
pattern the design can exhibit. "That cannot happen here" is an acceptable answer only with
the reason.
Decision block
Use the catalogue when:
- an incident has a shape you recognise but cannot name, so the search terms are unknown
- a postmortem must state a cause class other teams can find later
- a design review needs a concrete list of failures to argue a design against
Avoid the catalogue when:
- the pattern is already named and its owner known — open that skill directly
- a single stack trace needs local defect analysis → debugging; sparse evidence alone cannot
establish or rule out a distributed mechanism
Prefer instead when:
- the question is which faults the system tolerates rather than what is happening now →
failure-models
- an outage is in progress and the question is which lever to pull → cascading-failures
Recognition index
| Observation |
Pattern |
Owner |
| Synchronised spike after a restart, deploy, TTL expiry or recovery |
Thundering herd |
cascading-failures |
| Dependency inbound rate rises while its success rate falls |
Retry storm |
retries-and-backoff |
| Failure spreads to services that never call the failing one |
Cascading failure |
cascading-failures |
| Caller gave up but downstream work is still running |
Timeout stacking |
timeouts-and-deadlines |
| Queue depth and latency grow without bound; goodput falls |
Unbounded queue growth |
rate-limiting-and-load-shedding |
| Pool acquisition timeouts on unrelated endpoints; FD or OOM errors |
Resource exhaustion |
concurrency-limiting-and-bulkheads |
| Node is up, health check green, answering ten times slower |
Gray failure / slow node |
failure-models |
| Only some callers/regions can reach a dependency |
Asymmetric partition |
failure-models |
| Two records for one intent; a side effect applied twice |
Duplicate processing |
delivery-semantics, idempotency |
| Two instances both believe they hold the lock or the leadership |
Split-brain |
distributed-locks-and-leases |
| Negative durations, leases expiring early, out-of-order timestamps |
Clock skew |
distributed-locks-and-leases |
| Errors only while a rollout is in progress, then they stop |
Version skew |
rpc-and-api-contracts |
| Everything is green and a downstream dataset stopped changing |
Absence of errors as an error |
slo-and-alerting |
| Error rate spiked but nothing is broken — or the reverse |
Expected vs unexpected errors |
rpc-and-api-contracts |
| Work completes long after anyone wanted it; results are rejected |
Stale or obsolete work |
task-queues-and-competing-consumers |
| A cleanup job removed far more rows or objects than intended |
Destructive cleanup |
this catalogue (guard rails) |
| One request produces millions of downstream operations |
Input explosion |
rate-limiting-and-load-shedding |
| An "optional" dependency's outage took the request path down |
Optional-dependency assumption |
failure-models |
| The replacement is more general, more distributed, less reliable |
Second-system effect |
architecture-decision-making |
| Trigger is gone but the system remains in a bad equilibrium |
Metastable failure |
cascading-failures |
| Independent replicas fail together on one shared dependency/change |
Correlated/common-mode failure |
failure-models |
| Data plane fails because discovery/control plane is unavailable |
Control-plane coupling |
failure-models, caching-strategies |
Rules
- An entry is a routing decision, not a remedy. If you find yourself implementing from an
entry, stop and open the owner skill; the entry omits the conditions that make the fix
correct.
- A symptom rarely identifies one pattern. Retry storm, cascading failure and
under-provisioning all show elevated latency and errors. Use the discriminator stated in the
entry — usually a second series whose direction differs — rather than the first match.
- Absence is not evidence of health. A monitoring stack built on error rates cannot see a
consumer that stopped, a job that did not run, or a producer that went quiet: there are no
errors because there are no requests. Every pipeline needs a liveness or freshness signal —
age of the newest record, time since the last successful run — alerted on independently.
- Do not use one undifferentiated error ratio. Separate protocol/client rejection,
dependency failure, server defect and business outcome, while retaining a bounded status
class/reason dimension. Whether a 4xx is expected depends on the contract; authentication
outages and rate-limit saturation can be service incidents too.
- Every rolling deploy is a mixed-version window. Compatibility direction depends on who
produces/consumes first, rollback requirements, persisted messages and database migration
order. Build a version-interoperability matrix and use expand/migrate/contract rather than
the slogan “both directions” without a time horizon.
- Destructive cleanup needs executable bounds, not only a dry-run count. Validate selection
inputs, preview candidates, bound each batch and cap the whole logical run across retries
and workers. Counting then deleting with a changed predicate/snapshot is a race; the reference
explains candidate identity and revalidation. Dry-run success alone does not establish safety.
- Bound fan-out in both contract and implementation. Enforce size/depth/range limits and
resource budgets. SQL
LIMIT bounds returned rows, not necessarily scanned rows, joins,
sorting or downstream fan-out; inspect actual work before calling the input bounded.
- Patterns with a dedicated skill are not duplicated here: poison messages and dead-letter
handling are
poison-messages-and-dlq, distribution skew is
hot-partitions-and-rebalancing, and the fault classes themselves are failure-models.
Return a small ranked hypothesis set with observed evidence, one discriminator and competing
explanation per hypothesis, owner skill, and the next bounded evidence request. Missing
telemetry must remain explicit. Do not claim a mechanism was confirmed by matching its name.
References
Gray Failure: The Achilles' Heel of Cloud-Scale Systems
RFC 9110 — HTTP semantics
Java 25 ScheduledExecutorService
RFC 5905 — Network Time Protocol v4
Overload and amplification patterns — thundering
herd, retry storm, cascading failure, timeout stacking, unbounded queue growth, resource
exhaustion, input explosion, duplicate processing and gray failure, each as symptom,
mechanism, where it hides, and owner. Read when the incident involves load, latency,
saturation or repeated effects.
Silent, temporal and operational patterns — absence
of errors, expected versus unexpected errors, version skew, stale work, destructive cleanup,
the optional-dependency assumption, the second-system effect, split-brain and clock skew.
Read when nothing is obviously overloaded, when the incident is tied to a deploy, a schedule
or a clock, or when the evidence is something that failed to happen.
1---2name: distributed-failure-catalogue3description: Evidence-oriented recognition index for recurring distributed failure shapes: overload amplification, gray and asymmetric failure, split ownership, stale work, mixed versions, correlated faults, silent stagnation and destructive automation. Use to turn incident observations into discriminable hypotheses and route each to the skill owning diagnosis and remediation. It is not a substitute for the owner skill or causal evidence.4---56# Distributed Failure Catalogue78## Purpose910Turn a symptom into a name, and a name into the skill that owns the fix. Distributed failures11recur in a small number of shapes; an engineer who can name the shape reaches the right12mechanism in minutes instead of rediscovering it during an incident.1314This skill deliberately **does not teach the fixes**. Every entry ends at an owner, because a15catalogue that also explained the remedies would drift out of step with the skills that own16them. Destructive cleanup is the explicit exception, with bounded guard guidance below.17Its value is recognition and routing — and, for a design review, a list of concrete18failures to argue a design against rather than a general appeal to robustness.1920## Workflow2122This is a protocol/operations catalogue, with no Java language minimum. The scheduled-task23reference uses the Java 25 API documentation for a long-standing contract. Inspect the target24runtime, scheduler/framework, client retry defaults and deployment configuration before25applying version-sensitive claims; this skill does not authorize upgrades or fault injection.26271. **Write down the observation, not the theory.** "Inbound rate rose while success rate28 fell", "the queue is empty and no alert fired", "duplicates 1.5 s apart". The index below29 is keyed on observations.302. **Build a shared timeline and denominator.** Record clock domains, timestamp uncertainty31 and sampling gaps; do not infer causal ordering from cross-host timestamps alone. Align deploys, topology changes, retries,32 offered load, admissions, attempts, goodput, saturation and freshness. Rates without33 logical-request/attempt denominators routinely misidentify amplification.343. **Match the recognition index**, then read the full entry and try to falsify the mechanism.35 Several patterns share a symptom; require its discriminator and a competing explanation.364. **Check "where it hides"** in code, config, sidecars, SDKs and control planes before accepting the match.37 A pattern you cannot locate in the system is a hypothesis, not a diagnosis.385. **Go to the owner skill for the fix.** Do not improvise a remedy from the entry — the39 entries are deliberately too short to implement from.406. **In a design review, walk the index as a checklist** and require an answer for each41 pattern the design can exhibit. "That cannot happen here" is an acceptable answer only with42 the reason.4344## Decision block4546```text47Use the catalogue when:48- an incident has a shape you recognise but cannot name, so the search terms are unknown49- a postmortem must state a cause class other teams can find later50- a design review needs a concrete list of failures to argue a design against51Avoid the catalogue when:52- the pattern is already named and its owner known — open that skill directly53- a single stack trace needs local defect analysis → debugging; sparse evidence alone cannot54 establish or rule out a distributed mechanism55Prefer instead when:56- the question is which faults the system tolerates rather than what is happening now →57 failure-models58- an outage is in progress and the question is which lever to pull → cascading-failures59```6061## Recognition index6263| Observation | Pattern | Owner |64| ------------------------------------------------------------------ | ------------------------------ | -------------------------------------- |65| Synchronised spike after a restart, deploy, TTL expiry or recovery | Thundering herd | `cascading-failures` |66| Dependency inbound rate rises while its success rate falls | Retry storm | `retries-and-backoff` |67| Failure spreads to services that never call the failing one | Cascading failure | `cascading-failures` |68| Caller gave up but downstream work is still running | Timeout stacking | `timeouts-and-deadlines` |69| Queue depth and latency grow without bound; goodput falls | Unbounded queue growth | `rate-limiting-and-load-shedding` |70| Pool acquisition timeouts on unrelated endpoints; FD or OOM errors | Resource exhaustion | `concurrency-limiting-and-bulkheads` |71| Node is up, health check green, answering ten times slower | Gray failure / slow node | `failure-models` |72| Only some callers/regions can reach a dependency | Asymmetric partition | `failure-models` |73| Two records for one intent; a side effect applied twice | Duplicate processing | `delivery-semantics`, `idempotency` |74| Two instances both believe they hold the lock or the leadership | Split-brain | `distributed-locks-and-leases` |75| Negative durations, leases expiring early, out-of-order timestamps | Clock skew | `distributed-locks-and-leases` |76| Errors only while a rollout is in progress, then they stop | Version skew | `rpc-and-api-contracts` |77| Everything is green and a downstream dataset stopped changing | Absence of errors as an error | `slo-and-alerting` |78| Error rate spiked but nothing is broken — or the reverse | Expected vs unexpected errors | `rpc-and-api-contracts` |79| Work completes long after anyone wanted it; results are rejected | Stale or obsolete work | `task-queues-and-competing-consumers` |80| A cleanup job removed far more rows or objects than intended | Destructive cleanup | this catalogue (guard rails) |81| One request produces millions of downstream operations | Input explosion | `rate-limiting-and-load-shedding` |82| An "optional" dependency's outage took the request path down | Optional-dependency assumption | `failure-models` |83| The replacement is more general, more distributed, less reliable | Second-system effect | `architecture-decision-making` |84| Trigger is gone but the system remains in a bad equilibrium | Metastable failure | `cascading-failures` |85| Independent replicas fail together on one shared dependency/change | Correlated/common-mode failure | `failure-models` |86| Data plane fails because discovery/control plane is unavailable | Control-plane coupling | `failure-models`, `caching-strategies` |8788## Rules8990- **An entry is a routing decision, not a remedy.** If you find yourself implementing from an91 entry, stop and open the owner skill; the entry omits the conditions that make the fix92 correct.93- **A symptom rarely identifies one pattern.** Retry storm, cascading failure and94 under-provisioning all show elevated latency and errors. Use the discriminator stated in the95 entry — usually a second series whose _direction_ differs — rather than the first match.96- **Absence is not evidence of health.** A monitoring stack built on error rates cannot see a97 consumer that stopped, a job that did not run, or a producer that went quiet: there are no98 errors because there are no requests. Every pipeline needs a liveness or freshness signal —99 age of the newest record, time since the last successful run — alerted on independently.100- **Do not use one undifferentiated error ratio.** Separate protocol/client rejection,101 dependency failure, server defect and business outcome, while retaining a bounded status102 class/reason dimension. Whether a 4xx is expected depends on the contract; authentication103 outages and rate-limit saturation can be service incidents too.104- **Every rolling deploy is a mixed-version window.** Compatibility direction depends on who105 produces/consumes first, rollback requirements, persisted messages and database migration106 order. Build a version-interoperability matrix and use expand/migrate/contract rather than107 the slogan “both directions” without a time horizon.108- **Destructive cleanup needs executable bounds**, not only a dry-run count. Validate selection109 inputs, preview candidates, bound each batch and cap the whole logical run across retries110 and workers. Counting then deleting with a changed predicate/snapshot is a race; the reference111 explains candidate identity and revalidation. Dry-run success alone does not establish safety.112- **Bound fan-out in both contract and implementation.** Enforce size/depth/range limits and113 resource budgets. SQL `LIMIT` bounds returned rows, not necessarily scanned rows, joins,114 sorting or downstream fan-out; inspect actual work before calling the input bounded.115- Patterns with a dedicated skill are not duplicated here: poison messages and dead-letter116 handling are `poison-messages-and-dlq`, distribution skew is117 `hot-partitions-and-rebalancing`, and the fault classes themselves are `failure-models`.118119Return a small ranked hypothesis set with observed evidence, one discriminator and competing120explanation per hypothesis, owner skill, and the next bounded evidence request. Missing121telemetry must remain explicit. Do not claim a mechanism was confirmed by matching its name.122123## References124125- [Gray Failure: The Achilles' Heel of Cloud-Scale Systems](https://www.microsoft.com/en-us/research/publication/gray-failure-achilles-heel-cloud-scale-systems/)126- [RFC 9110 — HTTP semantics](https://www.rfc-editor.org/rfc/rfc9110)127- [Java 25 `ScheduledExecutorService`](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html)128- [RFC 5905 — Network Time Protocol v4](https://www.rfc-editor.org/rfc/rfc5905)129130- [Overload and amplification patterns](references/overload-and-amplification.md) — thundering131 herd, retry storm, cascading failure, timeout stacking, unbounded queue growth, resource132 exhaustion, input explosion, duplicate processing and gray failure, each as symptom,133 mechanism, where it hides, and owner. Read when the incident involves load, latency,134 saturation or repeated effects.135- [Silent, temporal and operational patterns](references/silent-and-operational.md) — absence136 of errors, expected versus unexpected errors, version skew, stale work, destructive cleanup,137 the optional-dependency assumption, the second-system effect, split-brain and clock skew.138 Read when nothing is obviously overloaded, when the incident is tied to a deploy, a schedule139 or a clock, or when the evidence is something that failed to happen.