Fault Tolerance

20 patterns for this goal

Agent systems fail constantly — services time out, data becomes corrupted, dependencies crash, and network partitions split systems. Fault-tolerance failures occur when agents don’t detect failures quickly, don’t recover from them cleanly, or apply recovery procedures that introduce new failures, such as cascading timeouts, partial rollbacks that leave data inconsistent, or failover delays so long that SLAs are already violated.

Key Takeaways

  1. Cascading Timeouts Amplify Failures: When Agent A times out waiting for Agent B, and Agent A’s timeout is longer than Agent B’s recovery time, agents pile up waiting on each other, saturating thread pools. Timeouts must be aggressive and decrease at each layer to prevent cascade amplification.

  2. Failover Delays Violate Recovery Time Objectives: Teams measure mean time to recovery (MTTR) in seconds or minutes, but automatic failover often takes 30-60 seconds just to detect the primary is down. By the time failover completes, SLA windows are already violated. Detection and failover must happen in milliseconds, not seconds.

  3. Partial Failures Leave Data Inconsistent: When a subset of steps in a recovery procedure succeed and the rest fail, the system is left in a partial state that cascades new failures downstream. Recovery procedures must be all-or-nothing, or intermediate states must be explicitly handled.

  4. Recovery Procedures Are Untested Until They Fail: A recovery procedure that was never executed during steady state may fail in production the first time it’s needed, because it encounters conditions that only appear during actual failure. Recovery paths must be tested regularly under failure scenarios.

Scope

Fault-tolerance failures cluster into five categories:

  • Cascade Mechanisms: Failures in one agent trigger failures in others due to timeouts, resource exhaustion, or cascading rollbacks. (cascade-amplification, cascade-detection-failure, cascade-isolation-failure, cascade-timeout-interaction)
  • Divergent Recovery: After a failure, different agents recover to different states, leading to inconsistency or data corruption. (cascade-divergent-recovery, failover-state-corruption, recovery-data-corruption, recovery-divergence)
  • Failover Delays & Detection: The system doesn’t detect that a primary has failed, or the detection takes too long, or failover is blocked waiting on the primary. (failover-correctness-failure, failover-delay-too-long, failover-data-loss)
  • Recovery Timing & Completeness: Recovery procedures take too long or only partially recover, missing steps that lead to cascading failures or SLA violations. (recovery-ordering-violation, recovery-partial-failure, recovery-procedure-untested, recovery-time-objective-miss)
  • Redundancy & Coordination: Redundant copies of data or services don’t stay coordinated during failure, or coordination mechanisms themselves fail. (redundancy-coordination-failure, single-point-of-failure, recovery-point-objective-miss)

When Fault-Tolerance Matters

  1. Mission-Critical Workflows: Systems where failures must be detected and recovered from in seconds, not minutes. Financial transactions, safety-critical control loops, or high-SLA services.

  2. Multi-Agent Distributed Systems: Systems with many agents running on different hardware. Any single component’s failure can cascade into failures in dependent agents if tolerance mechanisms aren’t in place.

  3. Stateful Services & Data Consistency: Systems where agents maintain state (orders, accounts, session data) that must be recovered consistently across failovers. Partial or divergent recovery corrupts that state.

Cross-Pattern Insight

Fault-tolerance is fundamentally about managing the time between failure and recovery. A failure is inevitable; the question is whether the system detects it fast enough and recovers cleanly enough to meet the SLA. Every fault-tolerance mechanism adds latency: detection takes milliseconds, failover takes more milliseconds, recovery procedures take seconds. But applications have SLAs measured in seconds or tens of seconds. If detection takes 5 seconds and recovery takes 10 seconds, the SLA is already violated before recovery completes. Robust fault-tolerance requires aggressive timeouts (hundreds of milliseconds, not seconds), rapid detection (through heartbeats or explicit pings, not waiting for requests to fail), and fast failover (into standby replicas, not rebuilding from scratch). Recovery procedures must be all-or-nothing (not leaving the system in a partial state), regularly tested (not just theoretically sound), and faster than the SLA window. Without aggressive timeouts, rapid detection, fast failover, and all-or-nothing recovery procedures, fault-tolerance is only a hope, not a guarantee.

Frequently Asked Questions

What is the difference between failover delay and recovery time objective? Failover delay is the time from when a primary fails to when the system detects the failure and switches to a backup. Recovery time objective (RTO) is the total time from failure to when the system is fully recovered and accepting traffic. Failover is just one component of RTO. If detection takes 5 seconds and failover takes 10 seconds and recovery takes 20 seconds, the total RTO is 35 seconds. If the SLA is 30 seconds, RTO is already violated.

How can an agent detect that a dependency has failed if it’s not getting requests? Active health checks: periodically send a ping or health check to a dependency and record the response. Don’t rely on request failures to detect dependencydown; by that time, your own requests are queued up timing out. Implement health checks at intervals much shorter than the timeout window (e.g., every 500ms for a 5-second timeout).

Why do partial failures leave the system in an inconsistent state? Because agents operate asynchronously and independently. If a recovery procedure is supposed to roll back changes in agents A, B, and C, and agent B’s rollback fails, agents A and C have already rolled back but B hasn’t. The system is now inconsistent. Mitigations: (1) make recovery all-or-nothing (stop the procedure if any step fails), (2) make recovery idempotent (safe to retry any step), or (3) explicitly handle partial states in downstream agents.

How can cascade amplification be prevented if timeouts are necessary? Use timeouts that decrease at each layer. Layer 1 (client -> API) might timeout at 5 seconds, Layer 2 (API -> backend service) at 4 seconds, Layer 3 (backend -> database) at 3 seconds. This ensures that if Layer 3 is slow, Layer 2 detects and fails fast before Layer 1 times out. Also use circuit breakers to fail fast if a dependency is already returning errors.

What should be tested for recovery procedures? At minimum: (1) recovery completes within RTO, (2) recovery produces a fully consistent state (run the same verification checks as in steady state), (3) recovery is idempotent (replaying recovery steps produces the same result), (4) recovery doesn’t produce cascading failures (downstream agents can resume normal operation), and (5) recovery works with partial prior failures (e.g., if some agents are already down before recovery starts).

Failure Patterns

PatternDescription
Cascade AmplificationA failure in one agent triggers timeouts in others, which trigger timeouts in their dependencies, amplifying latency across the system.
Cascade BranchingA single failure branches into multiple dependent failure cascades, affecting different parts of the system simultaneously.
Cascade Detection FailureThe system doesn’t detect that a cascade has begun, allowing it to spread unchecked.
Cascade Divergent RecoveryDifferent agents in a cascade recover to different states, leaving the system inconsistent.
Cascade Isolation FailureA failure spreads from one agent or service to others because isolation mechanisms didn’t work.
Cascade Resilience FailureResilience mechanisms (circuit breakers, rate limiters) fail under cascade load or misconfiguration.
Cascade Timeout InteractionTimeouts at different layers compound or interact, causing cascading failures instead of graceful degradation.
Failover Correctness FailureFailover to a backup produces incorrect results because the backup is out of sync or misconfigured.
Failover Data LossData in flight or recently committed is lost when failing over from primary to backup.
Failover Delay Too LongDetection and failover take so long that SLA is already violated before the system recovers.
Failover State CorruptionState on the backup diverges from the primary during normal operation; failover switches to corrupt state.
Recovery Data CorruptionRecovery procedure inadvertently corrupts data while attempting to restore consistency.
Recovery DivergenceDifferent agents executing recovery procedures independently end up with divergent state.
Recovery Ordering ViolationRecovery steps are applied out of order, leaving the system in an invalid intermediate state.
Recovery Partial FailureSome recovery steps succeed while others fail, leaving the system in a partially recovered state.
Recovery Point Objective MissData loss during a failure exceeds the configured recovery point objective (RPO).
Recovery Procedure UntestedA recovery procedure was never executed until needed in production and fails when invoked.
Recovery Time Objective MissRecovery takes longer than the configured recovery time objective (RTO).
Redundancy Coordination FailureRedundant copies become uncoordinated; failover switches to a stale or divergent replica.
Single Point of FailureA component lacks redundancy; its failure brings down the entire system.

Total: 20 patterns

  • Cascade-Failures — cascade propagation mechanisms are the primary concern in cascading-failures; fault-tolerance addresses recovery from cascades
  • Recovery-Mechanisms — dedicated to recovery procedures and ensuring they complete within RTO
  • Monitoring-and-Alerting — rapid detection of failures is a prerequisite for fast recovery
  • State-Consistency — divergent recovery often stems from inconsistent state management
  • Dependency-Management — dependencies are a common failure source; timeouts and circuit breakers mitigate dependent failures

Cascade Amplification

Frequency: Common
Category: Operations

An agentic system experiences a small, low-severity failure in one component — a single slow dependency, a handful of dropped requests, a brief queue backup — and instead of staying proportionate, the failure grows in magnitude as it propagates through downstream components. Each hop adds retries, duplicate work, or overcorrection, so a fault that started as a 2% error rate in one service arrives at the edge of the system as a full outage. The agent-specific twist is that autonomous retry loops and multi-step planning amplify faster than in traditional systems, because an agent facing a transient tool failure often retries the entire multi-step plan rather than the single failed call.

Cascade Branching

Frequency: Occasional
Category: Operations

A single triggering failure fans out into multiple independent cascades across unrelated subsystems, rather than propagating along one dependency chain. This happens when the failing component is a shared dependency consumed by several otherwise-independent subsystems (a shared auth service, a shared vector store, a shared message bus), so the initial fault triggers parallel, uncoordinated cascades that each unfold on their own timeline and are handled by different on-call teams who have no visibility into each other's incident. Unlike a single deepening cascade, branching multiplies the number of simultaneous incidents an organization has to manage at once.

Cascade Detection Failure

Frequency: Common
Category: Operations

A cascading failure that originates from a single root cause and propagates through several dependent components is not recognized as one incident. Instead, monitoring and on-call responders see a series of alerts from different services and open separate tickets, each investigated independently as if unrelated. Because no one is looking at the whole picture, responders spend time fixing symptoms in each affected service without ever addressing the shared trigger, and the incident often "resolves" temporarily in one place only to resurface in another minutes later.

Cascade Divergent Recovery

Frequency: Occasional
Category: Operations

After a cascading failure hits several components, each component recovers independently — resuming from its own local checkpoint, cache, or retry queue — without coordinating with the others on what the "true" post-incident state should be. The result is that components which were consistent before the cascade come back online in mutually inconsistent or conflicting states: one service thinks an order is confirmed, another thinks it was cancelled, and a third has no record of it at all. This is distinct from a single component failing to recover correctly; the problem is specifically that multiple components recover to different, incompatible versions of the truth.

Cascade Isolation Failure

Frequency: Occasional
Category: Operations

A system has bulkheads in place — separate connection pools, separate thread pools, separate tenant shards, separate rate limits — intended to contain a failure to the subsystem where it originates. During an actual cascade, the isolation boundary turns out to be leaky: a shared resource that was assumed to be partitioned (a shared thread pool, a shared database instance, a shared upstream dependency, a shared control plane) is in fact common to both the failing subsystem and the ones meant to be protected, so the failure crosses the boundary anyway. The bulkhead exists on paper and in the architecture diagram, but not in the actual runtime resource graph.

Cascade Resilience Failure

Frequency: Common
Category: Operations

The very mechanisms deployed to make a system resilient — retries, circuit breakers, health-check-triggered auto-restarts, failover — become active contributors to a cascading failure instead of containing it. A retry policy that seemed reasonable in isolation adds load to an already-struggling dependency; a circuit breaker's half-open probe traffic re-triggers the failure it just tripped on; an auto-restart policy cycles a struggling instance in a tight loop that never lets it recover. This pattern is specifically about resilience infrastructure making things worse, distinct from cascade-amplification (which is about magnitude growth generally) and cascade-timeout-interaction (which is about timeout settings specifically).

Cascade Timeout Interaction

Frequency: Common
Category: Operations

Different layers in a call chain are configured with timeout values that were each set reasonably in isolation but interact badly when combined, actively amplifying a cascade instead of bounding it. The classic bad pattern is an upstream timeout that is shorter than or too close to a downstream timeout, so the caller gives up and retries while the original call is still in flight and still consuming resources on the downstream system — doubling load without reducing it. This is a distinct, specific mechanism from general cascade-amplification: the trigger here is specifically the numeric relationship between timeout values at different layers, not retry policy or resilience-mechanism design broadly.

Failover Correctness Failure

Frequency: Occasional
Category: Operations

A failover mechanism does exactly what it's supposed to on the surface — it detects the primary's failure, promotes a standby, and traffic resumes flowing within the expected time — but the standby produces incorrect results once it's live. This is distinct from failover being slow (failover-delay-too-long) or losing data in flight (failover-data-loss): here the mechanics of the switch itself work, but the standby was running different code, stale configuration, an outdated model version, or an incomplete replica of reference data, so it silently serves wrong answers with full apparent availability.

Failover Data Loss

Frequency: Occasional
Category: Operations

When failover to a standby is triggered, writes that were in flight to the primary at the moment of failure — accepted by the client as successful, or in the process of being processed — never make it to the standby and are permanently lost. This is distinct from replication lag causing the standby to be generally behind (recovery-point-objective-miss is the measurement of that gap); this pattern is about the specific in-flight requests that were being processed at the exact instant of the failure, which fall into a gap between "already acknowledged to the client" and "durably replicated to the standby."

Failover Delay Too Long

Frequency: Common
Category: Operations

The failover mechanism eventually works — the standby is correct, no data is lost, no state is corrupted — but it takes materially longer to complete than the service's defined SLA or failover-time objective, extending customer-visible downtime well beyond what was promised or designed for. This is purely a timing failure: every other part of the failover (detection, promotion, correctness) can be functioning as designed, but the accumulated latency across detection, decision, and cutover steps blows through the target window.

Failover State Corruption

Frequency: Rare
Category: Operations

During the process of transferring state to a failover instance — replicating in-memory session data, migrating an in-progress agent execution context, transferring a partially-written data structure — the state itself becomes corrupted in transit, so the standby comes up with internally inconsistent or malformed data rather than a clean (if slightly stale) copy. This differs from failover-data-loss (specific writes missing entirely) and failover-correctness-failure (standby running stale-but-internally-consistent code/config): here the transferred state is actively broken — partial objects, torn records, mismatched cross-references — because the transfer mechanism itself was not atomic or crash-safe.

Recovery Data Corruption

Frequency: Rare
Category: Operations

The process of recovering a system after a failure — replaying a write-ahead log, re-running a batch job from a checkpoint, restoring from a snapshot combined with incremental logs — itself introduces data corruption, rather than faithfully restoring the pre-failure state. A partial write during log replay, a crash that interrupts the recovery process itself mid-way, or an off-by-one in checkpoint/log-offset alignment can leave the recovered system with malformed or partially-applied data. This is specifically about the recovery mechanism damaging data, as opposed to recovery simply being slow (recovery-time-objective-miss) or replaying events out of causal order (recovery-ordering-violation).

Recovery Divergence

Frequency: Occasional
Category: Operations

A single instance that recovers from a failure — restarting after a crash, restoring from a snapshot, resuming from a checkpoint — ends up in a state that differs from what its pre-failure state actually was, even though the recovery process completes without error and reports success. This is the single-instance version of the problem (as opposed to cascade-divergent-recovery, which is about multiple components recovering into mutually inconsistent states relative to each other): here, the concern is purely whether the one recovered instance matches its own prior true state, regardless of what any other component believes.

Recovery Ordering Violation

Frequency: Occasional
Category: Operations

During recovery, logged operations are replayed in an order that violates the causal dependencies between them — an operation that logically depended on an earlier one is applied before it, or two operations that must be applied in a specific relative order are applied out of sequence — producing a state that no valid execution of the original system could ever have reached. This is distinct from recovery-data-corruption (which is about a single operation being malformed or partially applied): here every individual operation replays correctly in isolation, but the sequence is wrong.

Recovery Partial Failure

Frequency: Common
Category: Operations

A recovery operation spanning multiple components or subsystems completes successfully for some of them but not others, leaving the overall system in a mixed state where part of it is back online with fresh, correct state and another part is still down, still on stale state, or stuck mid-recovery. Unlike cascade-divergent-recovery (where every component recovers but into mutually inconsistent states), this pattern is about recovery simply not finishing everywhere — some components never complete recovery at all, and the system limps along in a half-recovered condition, often without anyone noticing because the components that did recover look healthy.

Recovery Point Objective Miss

Frequency: Occasional
Category: Operations

The organization has a defined Recovery Point Objective (RPO) — the maximum acceptable amount of data loss measured in time, e.g. "no more than 5 minutes of data may be lost in any failure" — and an actual incident loses more data than that objective allows. This is a measurement-and-commitment failure specifically about the RPO number itself: the system's actual replication/backup cadence, under real failure conditions, produces a larger data-loss window than what was promised to stakeholders, discovered only when a real failure exposes the gap between designed and actual RPO.

Recovery Procedure Untested

Frequency: Common
Category: Operations

A documented recovery or disaster-recovery procedure exists — a runbook, an automated failover script, a restore-from-backup process — but has never actually been executed end-to-end against a real or realistic failure. When a real failure finally occurs and the procedure is invoked for the first time, it fails: a step references infrastructure that no longer exists, a credential has expired, a script depends on a manual precondition nobody remembers to satisfy, or the procedure simply takes far longer than anyone expected because nobody had a real timing baseline. The defining feature of this pattern is that the failure is discovered at the worst possible time — during an actual outage — rather than during a drill.

Recovery Time Objective Miss

Frequency: Common
Category: Operations

The organization has a defined Recovery Time Objective (RTO) — the maximum acceptable duration of an outage, e.g. "service must be restored within 30 minutes" — and an actual incident's total recovery time exceeds it. This pattern is specifically about the RTO commitment being broken, as a measurable, reportable event distinct from general slowness: it requires a documented target and an actual, measured overrun against that target, and is the aggregate/governance-level counterpart to specific timing failures like failover-delay-too-long (which describes the mechanics of why failover itself is slow).

Redundancy Coordination Failure

Frequency: Occasional
Category: Operations

A system runs multiple redundant instances of the same agent, worker, or failover component deliberately, for availability — but the instances have no coordination mechanism (a lock, a lease, a consensus protocol) governing who acts when, so two or more of them independently decide they are the one responsible for a given task and both act on it. This produces either duplicate execution of a side-effecting action (two remediation scripts both restart the same service, two agent replicas both send the same customer notification) or an outright split-brain, where two instances each believe themselves to be the sole active primary and take conflicting, contradictory actions on the same shared resource at the same time.

Single Point of Failure

Frequency: Common
Category: Operations

A critical agent, tool, service, or piece of shared infrastructure has exactly one instance in the architecture, with no redundant standby, no alternate path, and no fallback that doesn't itself depend on the same component — so that component's failure takes down every workflow that depends on it, directly or transitively, all at once. This is an architectural gap, not a failure that unfolds once triggered: the system was designed (or, more often, organically grew) without redundancy for a component that turned out to be load-bearing for far more of the system than anyone tracking "what's critical" realized at the time it was introduced.