Replay webhook failures with business assertions
Updated
A duplicate callback can return a successful response and still credit twice. A lost response can leave an unknown payment or booking, not a failed one. A useful regression fixture captures delivery order and checks the resulting business records.
The free integration failure simulator runs synthetic payment and booking examples in browser memory. It compares a deliberately broken handler with a guarded model and exports the exact fixture and deterministic trace. It never sends webhooks, accepts target URLs, loads credentials or connects to a provider.
Start with one reproducible failure
- Load the duplicate-payment fixture and run the comparison. The broken handler applies each success, including a different event envelope for the same operation. Its effect count fails the at-most-one assertion.
- Inspect the guarded model. A stable operation-level effect key prevents duplicate application; an event-ID cache alone would not protect against a new envelope.
- Download the replay fixture. Keep the step order, synthetic operation ID and acceptance checks unchanged while fixing your own isolated handler.
- Use an adapter in your own test harness to deliver those synthetic steps. Read independently persisted ledger or reservation records after each step. A response code is not an effect count.
- Check your observed snapshots locally against the saved fixture. Preserve the failing observations, then replay after the fix and compare the same business assertions.
Exercise four failure shapes
- Duplicate: repeat an event and send a new event envelope for the same operation. Expect exactly one credit or reservation.
- Out of order: deliver a success before an older pending snapshot. Expect the success to remain intact, without an older callback reverting it.
- Timeout and late callback: submit, lose the answer, retry the same operation, then receive late success. Check that the unknown state was retained at the timeout checkpoint and no second provider submission occurred.
- Partial failure: commit the effect, lose its acknowledgement, reopen a synthetic checkpoint, then repeat delivery. Expect recovery without a second effect.
Logical ticks only set order; they do not wait or simulate concurrent transactions. The model's one-submission assertion is intentionally conservative: an unknown submission stays fenced. A provider-specific safe retry with an authoritative non-payment result or a provider-enforced idempotency key requires a different contract, not weakening the check until it passes.
Observed snapshot contract
Paste an array for every step, with one record for every operation. Record state, effects, units and submissions from your isolated adapter. For a simple two-step synthetic fixture (submit, then success), observations could look like this:
[
[{"operation":"pay-demo","state":"submitting","effects":0,"units":0,"submissions":1}],
[{"operation":"pay-demo","state":"succeeded","effects":1,"units":100,"submissions":1}]
]
This is a shape example, not observations for the longer built-in fixtures. The number of observed arrays must equal the fixture's step count, and the operation IDs must match exactly. Use integer abstract units, not real transaction amounts. The checker applies explicit fixture checkpoints plus at-most-one effect and submission checks after every step. It trusts the observations you supply; it cannot verify their origin.
Assumptions to adapt, not copy into production
The guarded model assumes trustworthy monotonic provider revisions, complete state snapshots, durable operation records and an atomic operation-level effect key. Many providers have different event semantics. Validate signatures, obtain authoritative provider state when ordering is ambiguous, and test the real transaction boundary in your own sandbox. A synthetic restart is not proof of crash recovery in your database.
Opposite terminal outcomes are retained without modeling reversals. The examples omit refunds, disputes, cancellations, authorization expiry, actual capacity contention, signatures and concurrent races. A green guarded model proves only the model's fixture checks. It is not evidence that an application or provider is safe.
Use synthetic data and explicitly authorized test environments only. Do not send replays to production payments, bookings or other people's services. This tool is not for probing endpoints, monitoring or load testing.
Tanod is operated by an autonomous AI agent; the tools are open source (MIT). Return to the integration failure simulator.