Practice Reliability engineering
Reliability patterns for enterprise integration
Four patterns decide whether an integration survives its dependencies, and each one buys something at a price worth stating. They are drawn here as they behave rather than as they are defined. Retry and dead-lettering carried the two integration case studies; idempotent processing is designed into the platform; circuit breaking is the one I reach for at an API boundary shared by several callers.
The patterns
Retry with backoff
01A transient fault: the endpoint was briefly unreachable, throttled, or slow enough to time out. The same request would succeed a moment later.
Scroll the diagram sideways
- When to reach for it
- When the operation is idempotent and the fault is genuinely transient. Bounded, always — an attempt limit and a growing interval.
- What it costs
- Latency amplification under load, and a retry storm if every caller backs off on the same schedule. Add jitter, or the retries synchronise and become the outage.
Dead-lettering
02A message that will never succeed: malformed payload, a contract that changed, a reference to something that no longer exists. Retrying it forever is just load.
Scroll the diagram sideways
- When to reach for it
- Immediately after the retry budget is exhausted. The queue needs a named owner, an alert and a runbook before it is switched on.
- What it costs
- An operational obligation. A dead-letter queue nobody watches is strictly worse than no dead-letter queue, because it looks like handling.
Circuit breaking
03A dependency that is down rather than slow. Every caller is queueing against it, holding connections, and the retries are making the recovery slower.
Scroll the diagram sideways
- When to reach for it
- In front of a downstream that can be overwhelmed, especially one shared by several callers. Needs a half-open probe to discover recovery.
- What it costs
- It fails requests that might have succeeded, and it moves the failure to the caller, who now needs a fallback. Tuning the thresholds is genuinely hard.
Idempotent processing
04At-least-once delivery doing exactly what it promises: the same message arriving twice, or a third party replaying yesterday because their side had an incident.
Scroll the diagram sideways
- When to reach for it
- Always, in a messaging estate. Key on a business identifier, not on a delivery or message id, which changes on redelivery.
- What it costs
- Every handler carries it, and there is no central enforcement — it lives or dies on code review. Storage for the seen-keys record, and a decision about how long to keep it.
Where these show up
Retry and dead-lettering carried both the ERP integration layer and the estate rescue, where redesigning the two together — bounded, owned, alerted — was my part of what moved the incident rate; idempotent processing is keyed on a business identifier in both, and all four are what the migration target patterns assume of anything built to them. Circuit breaking is the one I reach for at an API boundary shared by several callers, and it is the pattern neither of those two pieces of work needed — though it is the one a colleague put in front of a fixed SOAP layer during the storm that first showed me a downstream failing under load. The longer argument is in Designing for the third party having a bad day.