
Circuit Breaker Pattern for API Workflows
One bad API can slow or stop your whole workflow. If I want to keep user-facing flows moving, I need to set timeouts, keep retries low, and open the circuit when failure signals stack up.
Here’s the short version:
- I treat 5xx errors, timeouts, connection failures, DNS issues, 408s, and 429s as breaker signals.
- I don’t count most 4xx errors like 400, 401, 403, and many 404s, because those usually point to a bad request, not a sick provider.
- I give each provider its own policy for timeouts, retries, backoff, open time, and half-open probes.
- I keep retries to 0 to 2 in user-facing flows, with exponential backoff plus jitter.
- I stop retries when the breaker is open.
- I use half-open probes to test recovery with a small number of trial requests.
- I make sure fallback paths are honest: cached reads, skipped optional steps, or queued writes are fine; pretending a write succeeded is not.
In plain terms: I’m trying to stop worker time, queue capacity, and connection slots from getting burned by a provider that is down, slow, or rate-limiting traffic.
A circuit breaker works through three states:
- Closed: requests go through and results are tracked
- Open: requests fail fast and no upstream call is made
- Half-open: a few test requests check whether the provider is back
This pattern is less about code style and more about control. If a workflow has a 12-second deadline, I need each attempt, each delay, and each fallback to fit inside that budget. For example, two 3-second attempts with one 2-second pause still leave time for a fallback path.
If I had to boil the article down to a checklist, it would be this:
- Define which failures count.
- Set per-attempt timeouts and one end-to-end deadline.
- Limit retries and add jitter.
- Open the circuit on recent failure count or rate.
- Probe recovery in half-open.
- Keep fallback paths honest.
- Watch open rate, fallback rate, probe success, retry suppression, and recovery time.
The core point is simple: a circuit breaker should protect the rest of the workflow from one unstable dependency, not just report that something failed.

Circuit Breaker Pattern: 3-State Flow & 7-Step Implementation Checklist
Circuit Breaker Pattern in Microservices
sbb-itb-fd1fcab
How the circuit breaker state model works
A circuit breaker lets requests move through in the closed state and keeps track of what happens. When failures go past a set count or rate within a given time window, the breaker switches to the open state. At that point, it fails fast instead of calling the upstream service, which helps protect workers and downstream web application development jobs.
Closed, open, and half-open states
These three states control how the breaker shields the workflow and how it comes back safely.
| State | Request behaviour |
|---|---|
| Closed | Requests pass; outcomes are tracked. |
| Open | Requests fail fast; no upstream API call. |
| Half-open | Limited trial requests test recovery. |
The half-open state acts like a cautious test run. After a cooldown period, the breaker allows a small number of trial requests through. If those requests succeed, the breaker moves back to closed. If they fail, it flips back to open.
State transition table
| From | To | Trigger |
|---|---|---|
| Closed | Open | Failures exceed the predefined threshold within the time window. |
| Open | Half-open | Cooldown period elapses. |
| Half-open | Closed | Trial requests succeed. |
| Half-open | Open | Trial requests fail. |
Next, you need to define the failures, timeouts, and retry limits that control when the breaker trips and when it can recover.
Set up failure detection, timeouts, and retry limits
A circuit breaker works best when failure rules, timeouts, and retries all follow one shared policy, especially within custom workflow automation systems.
Choose which failures should trip the breaker
Not every error means the upstream service is in trouble. Transient failures are the ones that should count toward the breaker threshold: connection refusals, DNS resolution errors, socket timeouts, HTTP 5xx responses, HTTP 408, and HTTP 429 rate-limit responses. These usually mean the provider is down for a moment, overloaded, or unable to respond in time. That’s exactly the kind of problem a breaker is meant to handle.
Client errors should not trip the breaker. HTTP 400, 401, 403, and most 404 responses usually mean the request itself is the issue: bad input, missing credentials, or the wrong endpoint. If you count those as breaker failures, you get a false signal. The upstream is doing its job, and opening the circuit won’t fix your request bug.
HTTP 429 needs extra care. If the provider sends Retry-After, follow it. If that delay is longer than the time left in your deadline, fail fast or queue the work.
It also helps to check idempotency before treating a timeout as safe to retry. A timed-out GET is usually fine to send again. A timed-out POST is different; it may already have worked, and only the response got lost. For non-idempotent operations, use a status check or reconciliation step instead of a blind retry.
Document timeout and breaker settings
Each third-party integration needs its own written policy. One global setting for every provider is a common trap. Providers vary in latency, rate limits, and recovery patterns, so a value that works for one can be way off for another.
Document these settings for every integration:
- connection timeout
- per-attempt timeout
- overall deadline
- retry limit
- backoff
- failure threshold
- rolling window
- open duration
- half-open probe count
The table below shows what each setting does and what can go wrong when it’s set badly.
| Setting | Purpose | Too low | Too high | Signal used to tune it |
|---|---|---|---|---|
| Connection and response timeout | Bound time spent on one upstream attempt | False failures during normal latency variation | Hung calls consume workers and connections | p95/p99 latency, timeout rate, and workflow deadline |
| Overall workflow deadline | Limit the complete operation, including retries | Incomplete work or excessive fallback | Slow customer responses and resource exhaustion | End-to-end completion time and service objective |
| Retry limit | Permit recovery from short-lived faults | Missed transient recoveries | Retry storms, duplicate work, and quota consumption | Recovery rate by attempt and upstream load |
| Backoff and jitter | Spread retries over time | Immediate retry bursts | Excessive user-visible delay | Retry arrival pattern, 429 rate, and recovery latency |
| Failure threshold or failure rate | Decide when to open the circuit | Circuit opens for isolated failures | Continued pressure on an unhealthy service | Error rate, sample count, and false-open events |
| Rolling-window duration | Define the period used for failure measurement | Noisy decisions from too little history | Slow response to a new outage | Traffic volume and incident duration |
| Open-state duration | Allow the upstream time to recover | Premature probes and repeated failure | Longer disruption after recovery | Time-to-recovery and half-open probe success |
| Half-open probe count | Test recovery before full traffic resumes | Insufficient evidence of recovery | Probe traffic can overload a fragile service | Probe success rate and upstream capacity |
Here’s a simple way to think about per-attempt timeout. Say a workflow has a 12-second deadline. A 3-second first attempt, one 2-second backoff, and a second 3-second attempt still leaves time for fallback. That’s the balance you want. Set these values from measured latency percentiles and the provider’s limits.
Set bounded retries without amplifying failures
Retries and circuit breakers solve different problems.
| Mechanism | Primary role | When it acts | Main design question |
|---|---|---|---|
| Timeout | Stop one call that is taking too long | During an individual attempt | How long can this attempt consume resources? |
| Retry | Reattempt a potentially transient failure | After a retryable response or network error | Is the operation safe and worthwhile to repeat? |
| Circuit breaker | Prevent calls likely to fail | After the configured failure evidence is reached | When should new calls be rejected or routed to fallback? |
For most synchronous, user-facing workflows, stick to zero to two retries. Go beyond that and you risk a retry storm, especially when many workers fail at once and all try to recover at the same time. Use exponential backoff with jitter. That means each delay gets longer than the last – say about 1, 2, 4, and 8 seconds – with a random amount added, and a cap so the workflow doesn’t stall.
Jitter matters because it spreads retry traffic out. Without it, a large group of clients can hammer the provider at the same moment right after an outage or throttling event.
Two rules should be fixed parts of the policy. First, stop retrying as soon as the circuit opens. That’s the whole point of the breaker: to stop the repeated calls retries would keep making. Second, set both a maximum attempt count and an overall retry deadline, so slow responses and backoff delays can’t quietly eat the full workflow budget.
Apply these limits in the workflow order next.
Build the protected API workflow
Apply the policy in the correct order
Once you’ve set your timeouts, retries, and breaker thresholds, plug them into each call path one dependency at a time. Every upstream service needs its own policy set. That means its own timeout, retry rules, breaker state, and fallback path.
Think of each dependency as its own lane. If one service starts dragging, you don’t want that mess spilling into everything else.
The order of these policies matters more than it might seem. Wrap each call like this: per-attempt timeout, then bounded retries for retryable transient faults, and then the circuit breaker around those retries. The timeout cuts off one hanging attempt. The retry gives short-lived faults a chance to clear. The breaker looks at the result after retries are spent – not at every failed try along the way – and decides whether the circuit stays closed or opens.
That order avoids a classic trap: tripping the breaker on every internal retry instead of on the final outcome. And if the breaker is already open, retries should stop right there. Retrying a rejection from an open breaker defeats fail-fast behaviour.
Handle fallback and half-open recovery safely
After the call order is set, decide what the workflow should return when the breaker opens. If the circuit is open, the response should match reality. A read can return cached or stale data, but it needs a clear label. An optional enrichment step can be skipped so the main transaction still goes through. A write can go onto a durable queue and return an accepted response. The one thing fallback must never do is pretend an upstream operation succeeded when it has not been confirmed.
Half-open recovery needs tight control. When the open interval ends, allow only a small number of probe requests before choosing whether to close the circuit or open it again. Don’t dump queued traffic back in all at once. Rate-limit it or let some of it expire during recovery.
Apply the pattern across SaaS integrations
In multi-service SaaS workflows, keep breaker state separate by provider and by type of work. Use different breakers, timeouts, and queues for each provider. Shared breaker state creates coupling fast; one slow document-processing service should not open the circuit for your identity provider.
The same logic applies to work classes. A bulk CRM sync running in the background should not eat up the connection slots or retry budget needed for a user-facing customer lookup. Split them with separate worker pools, concurrency limits, and queues. When a provider is unhealthy, drop optional background work first and protect interactive requests.
If your platform runs optional AI enrichment, give that call its own breaker too. That way, the core transaction can still finish even if the enrichment step falls over.
Monitor, test, and tune recovery
Track the right resilience signals
After deployment, keep a close eye on recovery behaviour so you can spot failures early. Focus on breaker-open rate, half-open success rate, fallback rate, retry suppression, and time-to-recovery.
Those signals tell you more than “something went wrong.” They show how the system is reacting under stress. For example, sustained fallback volume after incidents can point to a slow-burn reliability issue upstream. That kind of pattern is easy to miss if you only watch error rates.
Use these metrics to decide which failure modes to inject.
Run failure-injection tests and confirm acceptance criteria
Use sandbox tests to show that the breaker behaves as expected under real failure patterns. Run these tests in a sandbox before release so you can verify recovery without touching production.
Test the full workflow automation path, not just the API call. A single request might look fine on its own, while the broader flow still breaks under delay or partial failure. Tools like Toxiproxy or Chaos Mesh can help you inject latency above the timeout threshold and simulate those conditions in sandbox.
Then confirm the breaker opens at the configured threshold and returns to closed only after half-open probes pass.
Your acceptance criteria should stay simple and measurable:
- Breaker opens at the threshold
- Half-open probes pass
- Traffic resumes
Conclusion: What to keep in place in production
Keep breaker monitoring active in production. Track the moments when the breaker opens, half-open probe attempts, retry suppression, fallback use, and recovery time. Those signals show you whether the breaker is doing its job or getting in the way.
If thresholds, timeouts, or fallback paths start to misfire, fix the settings fast. Small config issues can snowball in production, especially when traffic is high and upstream services get shaky.
In production, the breaker should protect user-facing flows first and absorb upstream instability second. That order matters. Users feel pain before dashboards do.
A well-tuned circuit breaker stops one failing API from dragging down the rest of the workflow. Keep it tuned, watched, and aligned with current upstream behaviour.
FAQs
When should I use a circuit breaker?
Use a circuit breaker when your distributed system relies on downstream services or external APIs that can fail on and off. It helps stop cascading failures, especially in high-latency setups where waiting for timeouts can tie up system resources.
It also helps stop infinite loops in AI agent tool calls and can trigger automated rollbacks when performance falls outside established service level objectives.
How do I choose timeout and retry limits?
Use a balanced approach so you don’t create needless interruptions or instability. A good starting point is conservative thresholds – for example, five to ten consecutive failures. That helps cut down on false positives.
Watch state changes and recovery times closely. If your settings are too strict, the circuit can trip too soon. If they’re too loose, failures may keep rolling through longer than they should.
It also helps to test under conditions that look like normal use, not just a clean lab setup. Run checks with realistic data volumes, traffic patterns, dropped connections, and malformed data. That makes it much easier to fine-tune your retry logic and timeout durations.
What happens when the circuit opens?
When the circuit opens, the system fails incoming requests right away instead of sending them to the broken service. That takes pressure off the downstream service and helps stop errors from rippling through the distributed system.
After a set cooldown period, it shifts to half-open to check whether the service has recovered before going back to normal operation.