
When a service stops responding, every new request may wait for another timeout. Repeated calls can tie up resources and make an outage spread to otherwise healthy parts of an application. A circuit breaker temporarily stops calls to a failing dependency and gives it a chance to recover.
The pattern does not fix the dependency or decide whether an earlier payment succeeded. It controls whether a new call should be attempted and gives the application an opportunity to return a clear response or use an appropriate fallback.
Closed, Open And Half-Open
In the closed state, calls flow normally and the breaker records outcomes. If a configured failure condition is met, it opens and rejects or short-circuits subsequent calls for a period. After that interval, a half-open state allows a limited number of trial calls. Success can close the breaker; further failure can open it again.

Consider a hypothetical checkout that calls a payment provider. If the provider repeatedly times out, the breaker can stop additional attempts for a short period and tell the customer that payment is temporarily unavailable. It should not claim the order is paid merely because a fallback page was displayed.
Different libraries use different windows, failure thresholds and state-sharing mechanisms. Check how the chosen implementation counts errors and how each application instance maintains its state. A breaker that opens on normal validation failures may block a healthy service; one that ignores timeouts may react too late.
Set Boundaries Around A Dependency
Choose a scope that reflects the failure being protected against. A single breaker for unrelated operations can prevent healthy calls when only one endpoint is failing. A separate breaker for every individual request can be too fragmented to identify a pattern. Use observed behavior and operational requirements to choose.
Pair the breaker with timeouts and resource limits. A breaker cannot act on a call that never returns unless the system bounds how long it waits. Limit concurrent work where a slow dependency could exhaust a connection pool. Define a fallback that is honest: a cached read may be appropriate in one situation, while a financial action may need to pause and show its status.
Retries And Payments Need Care
Retries can help with transient failures, but uncontrolled retries add load and can create duplicate side effects. If a payment request times out, the provider might have accepted it even though the response was lost. Check the provider's status or use its documented idempotency mechanism before retrying. If the outcome remains unknown, keep the transaction in an appropriate pending state for reconciliation.
A circuit breaker is not a substitute for that reconciliation. It also does not guarantee that downstream work was completed when the breaker closes. The application must track each operation and communicate what is known to the customer and the team.
Test Recovery As Well As Failure
Exercise the closed, open and half-open paths with controlled failures. Check that calls stop when intended, that the application responds within its limits and that only a bounded number of recovery probes are sent. Test a failed probe and a successful recovery, including multiple application instances if they have independent state.
Monitor the number of short-circuited calls, dependency latency and recovery attempts. Connect the alert to an owner and a runbook. For background workflows that must resume after interruptions, the durable execution guide covers retries and uncertain outcomes in more detail.

