Delivery-system failure rehearsals
Inject bounded failures around release decision points and validate independent safety, recovery, and data-integrity oracles rather than merely watching a controller restart.
On this page
The question for today
What you’ll understand
- Select fault points that expose uncertain external effects and stale evidence.
- Define independent oracles for release exposure, revision identity, and durable-state correctness.
- Count a finite rehearsal matrix without claiming exhaustive distributed-schedule coverage.
A delivery system is part of the service it changes. Its own restart, stale cache, unavailable metrics, partial routing update, or failed migration can create an incident. Rehearsals turn those possibilities into inspectable traces. The strongest result is a demonstrated invariant and recovery behavior under a specified fault, not a screenshot showing that the controller eventually returned to a green status.
Place faults at meaningful boundaries
Choose points before and after an external effect, durable progress update, evidence check, or destructive state transition. A crash after traffic changed but before acknowledgment tests a different path from a crash before the request was sent. Delay or duplicate responses, return stale health for an earlier revision, remove telemetry, and interrupt an abort as separate cases. Use a bounded isolated environment or another explicitly controlled scope with an independent stop mechanism. Scope selection and cleanup matter because a misselected target can test an unrelated system rather than the intended release protocol.
Start from a known artifact, configuration, routing state, and data snapshot. Record operation identities, generation numbers, fault timing, and what each component could observe. The controller may need to relist or reobserve after disconnection; a replayed event should not be assumed fresh. A timed-out operation can already have completed externally. Rehearse restarts and compensations with that uncertainty intact rather than resetting the target to the happy path before the resumed controller can encounter the difficult state.
The oracle must observe more than the mechanism under test
Define forbidden observations: an unapproved digest receives traffic, exposure exceeds its allowed cap, stale evidence promotes a new revision, compensation happens twice, or committed data violates the business invariant. Define liveness separately, including a bounded expected recovery condition when dependencies return. Use target-side routing observations, request traces, data reconciliation, and an independent workload probe where appropriate. The controller's status is one observation, but relying on that same controller to announce whether its own safety rule was violated creates a weak oracle.
Include mixed-version data cases. Let the candidate write legitimate new-format records before testing a rollback or forward repair. Keep long-lived sessions active through cutover, and distinguish retryable requests from already completed non-idempotent effects. Test missing and inconclusive metrics so that absence does not become a synthetic pass. For every case, name the evidence that would fail the test and preserve it even if the system later recovers. A temporary invariant violation still matters when a final steady-state dashboard looks normal.
A passing finite matrix leaves explicit limits
Run deterministic traces first so a failure is reproducible, then add controlled timing variation or property-based exploration where it can reveal additional interleavings. Record the tested versions and assumptions. Passing a finite set does not prove correctness under every crash, arbitrary delay, Byzantine response, or concurrent operator action. Convert a discovered counterexample into a durable regression case and fix the protocol or invariant rather than merely lengthening a sleep until the trace passes. Rehearse the emergency stop and cleanup path as part of the same operational capability.
The Markov instrument illustrates a distinction between recovery and recurrence, not fault injection. Reset, set both p=0.5 and q=0, predict state-one probability 0.75 after two Steps, then Step twice. Separately Reset, set both p=0.5 and q=0.5, predict 0.5 after two Steps, then Step twice. It starts in state zero and displays exact two-state probabilities. The first state-one condition is absorbing; the second permits return. Neither setting tests a controller, data invariant, or real failure schedule. Explain why eventual recovery in a model is weaker than preventing every forbidden exposure in a rehearsal trace.
Work it through
A finite checkpoint matrix can already be substantial
A rehearsal design has six ordered checkpoints and four discrete fault choices at each. Include every single-checkpoint case and every pair of different checkpoints with one fault at each. Repeat each case ten times, with an assumed complete isolated-run duration of twenty seconds.
Single-checkpoint cases number 6×4=24. Selecting two different checkpoints gives binomial(6,2)=15 pairs, with 4×4=16 fault assignments per pair, or 240 two-checkpoint cases.
The defined matrix contains 24+240=264 cases. Ten repetitions produce 2,640 runs, each with an independently reset starting state under the stated design.
Serial runtime is 2,640×20=52,800 seconds, or fourteen hours forty minutes. That substantial matrix still excludes other timing schedules, extra faults, invalid combinations, and behaviors outside the chosen checkpoints.
Count and prioritize a defined fault model. Large test volume is not an excuse to claim exhaustive coverage of a distributed delivery system.
The living notebook
Explore the model
Interactive lab · markov
Recovery and recurrence are different observations
Reset, set both p=0.5 and q=0, predict state-one probability 0.75 after two Steps, then Step twice. Separately Reset, set both p=0.5 and q=0.5, predict 0.5, then Step twice. This exact two-state distribution is not a controller fault injector or safety verifier and samples no real traces.
- P(state 1) at step 0
- 0%
- Stationary P(state 1)
- 60%
- Chain behavior
- Monotone convergence
Exact finite-step probabilities for a two-state chain starting in state 0, not sampled trajectories. Playback advances two transitions per second. When p = q = 0 every distribution is stationary; when p = q = 1 the chain alternates forever. A single zero transition creates an absorbing state. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA model that often reaches a recovered state does not establish that a release system never violated an invariant along the way.
Pause & reason
Check your understanding
Your turn
Try it yourself
Four ordered checkpoints each have three discrete fault choices. Count single-checkpoint cases and two-different-checkpoint cases under the same convention. Name one class of behavior the count omits.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Use 4×3 and binomial(4,2)×3² separately.
Compare with the solution
There are twelve single-checkpoint cases and 6×9=54 two-checkpoint cases, or sixty-six in the combined matrix. The model omits continuous timing choices, additional simultaneous faults, multiple faults at one checkpoint, and arbitrary message schedules. Each case also needs an explicit oracle; a count of executed experiments is not itself correctness evidence.
Keep the idea
Take it with you
- Inject failures around real effect and evidence boundaries with a controlled scope.
- Validate independent safety, data, and liveness oracles throughout the trace.
- A finite rehearsal matrix has defined coverage limits and should grow from discovered counterexamples.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.