Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Symfony Circuit Breaker Bundle Laravel Package

tourze/symfony-circuit-breaker-bundle

Lightweight Symfony bundle that adds circuit breaker protection to your services. It prevents cascading failures by detecting failing dependencies and short-circuiting calls until they recover, with simple configuration and seamless integration for resilient PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — that framing matters more than anything else at 0.0.1. There is no Laravel service provider, no facade, no config/circuit_breaker.php, and no package auto-discovery. Treat the first hour as reconnaissance rather than installation.

Where to look first, in order:

  1. composer.json — the Symfony framework/http-kernel version constraints. This tells you whether it can coexist with the Symfony components Laravel already ships, and whether it targets a Symfony version newer than Laravel's underlying components.
  2. The bundle class (*Bundle.php) and DependencyInjection/ — the Extension and Configuration classes are the real public API. They define the config tree and the service IDs, which is what you actually need to know.
  3. The breaker implementation itself — the state machine (closed → open → half-open), the failure counting, and critically where state is stored (in-process vs. a cache/PSR-6 pool). This single detail determines whether the package is useful in a multi-worker PHP-FPM or Octane deployment.

The 0.0.1 release notes are only a link to the commit list, so there is no documented surface yet. Read the diff, not the changelog.

First use case: guard one outbound dependency — a payment gateway, shipping-rate lookup, or third-party auth endpoint — where you want to fail fast and serve a degraded response instead of letting slow timeouts cascade. Start with exactly one call site. Do not wrap your whole HTTP client on day one; you want to watch the state transitions and tune thresholds against real traffic before generalizing.

Implementation Patterns

On the Symfony side (if you have a Symfony app or a shared monorepo): register the bundle in config/bundles.php, then configure it under config/packages/. Services are wired through the DI container, so the intended pattern is to inject the breaker (or a decorated client) into the service that makes the outbound call.

On the Laravel side, there are three realistic options:

  • Port the concept, not the package. The state machine is small — a failure counter, a cooldown timestamp, and a half-open trial. Reimplementing it as a CircuitBreakerManager singleton with a cache-backed store takes an afternoon and gives you Laravel-native config, facades, and testing helpers. For most Laravel teams this is the right call at 0.0.1.

  • Bridge it. If you want the exact upstream semantics, write a small service provider that registers the Symfony Configuration/Extension output, or hand-wire the breaker class as a singleton. You are now maintaining a compatibility shim across two ecosystems — budget for that.

  • Decorator wrapper. Whichever route you take, wrap an existing client rather than scattering if ($breaker->isOpen()) checks through controllers. In Laravel, bind the decorated client into the container so call sites are unchanged:

    $this->app->bind(PaymentClient::class, fn ($app) =>
        new CircuitBreakerClient(
            new HttpPaymentClient(),
            $app->make(CircuitBreakerManager::class)->for('payments')
        )
    );
    

Other patterns worth adopting early:

  • Per-dependency breakers, not per-application. A breaker named payments should not be tripped by failures from shipping. Resolve by name from a manager.
  • Fallbacks at the edge, not exceptions in the middle. Return a cached value, a queue-and-retry acknowledgement, or a clear 503 — a CircuitOpenException bubbling into a Blade view is not a user experience.
  • Log state transitions explicitly. Closed→open and open→closed are the only events that matter for on-call; everything else is noise.
  • Feature-flag the breaker. You want to disable it in one config change when it mis-tunes in production at 2am.

Gotchas and Tips

  • 0.0.1 means no backward-compatibility promise. Pin the exact version ("tourze/symfony-circuit-breaker-bundle": "0.0.1"), not a caret range. A 0.0.x patch release can and will rename classes.
  • The release notes contain zero information. "Full Changelog" pointing at the commit list is not a changelog. Before adopting, read the commits and the README; before upgrading, diff the public classes yourself.
  • Symfony bundle ≠ Laravel package. No extra.laravel.providers, no auto-discovery, no php artisan vendor:publish. Any tutorial you find assuming a service provider will not apply.
  • In-memory state is a trap in PHP. If the breaker stores failure counts in a property on a singleton, it resets on every request in FPM and is per-worker under Octane. That is not a circuit breaker — it is a no-op that looks like one. Verify it uses a shared cache (Redis, database, filesystem) before trusting it in production.
  • Half-open needs a concurrency guard. If the cooldown expires and 200 concurrent requests all become trial requests, you have re-created the outage you were protecting against. One trial at a time, others fail fast.
  • Thresholds are workload-specific. A 50% failure rate over 10 requests is very different on a 5 rps endpoint vs. a 500 rps one. Make both the failure threshold and the cooldown window configurable, and start conservative (trip late, recover late) rather than aggressive.
  • Extension points: in Symfony, a compiler pass or the Configuration tree; in Laravel, container bindings and an interface (CircuitBreakerStore) you can swap for a fake in tests. If the package's state store isn't already abstracted behind an interface, that is the first thing to wrap.
  • Check the Symfony version ceiling against Laravel's pinned components. Laravel 11/12 ship specific Symfony majors; a bundle requiring a newer one will create an unresolvable dependency graph in a monorepo.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels