A storage-agnostic Circuit Breaker implementation for PHP with optional Symfony integration.
Protect your application from cascading failures when external services (APIs, payment gateways, email services) go down.
This package is not yet published on Packagist. Add the repository to your composer.json:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/hugronaphor/circuit-breaker"
}
]
}Then require the package:
composer require hugronaphor/circuit-breaker:dev-main# For Doctrine storage (database persistence)
composer require doctrine/orm
# For DynamoDB storage (AWS Lambda)
composer require async-aws/dynamo-dbuse Hugronaphor\CircuitBreaker\CircuitBreaker;
use Hugronaphor\CircuitBreaker\Storage\InMemoryStorage;
$storage = new InMemoryStorage();
$circuitBreaker = new CircuitBreaker(
storage: $storage,
serviceName: 'payment_api',
failureThreshold: 3, // Open circuit after 3 failures
recoveryTimeoutSeconds: 60, // Try again after 60 seconds
);
$result = $circuitBreaker->call(
operation: fn() => $this->paymentGateway->charge($amount),
fallback: fn() => $this->queuePaymentForRetry($amount),
);use Hugronaphor\CircuitBreaker\CircuitBreakerFactory;
use Hugronaphor\CircuitBreaker\Storage\InMemoryStorage;
$factory = new CircuitBreakerFactory(
storage: new InMemoryStorage(),
defaultFailureThreshold: 3,
defaultRecoveryTimeoutSeconds: 60,
);
$paymentCircuit = $factory->create('payment_api');
$emailCircuit = $factory->create('email_service', failureThreshold: 5); ┌──────────┐ Failures reach ┌──────────┐
│ CLOSED │ ─────── threshold ──────► │ OPEN │
│ (normal) │ │ (reject) │
└──────────┘ └──────────┘
▲ │
│ Recovery timeout
Test succeeds expires
│ ▼
└─────────────────────────────── ┌──────────┐
Test fails ────────►│HALF-OPEN │
(back to OPEN) │ (test) │
└──────────┘
| State | Behavior |
|---|---|
| CLOSED | Normal operation. Requests pass through. Failures are counted. |
| OPEN | Circuit is tripped. All requests immediately use fallback. |
| HALF-OPEN | After recovery timeout, one test request is allowed through. |
// config/bundles.php
return [
Hugronaphor\CircuitBreaker\Symfony\HugronaphorCircuitBreakerBundle::class => ['all' => true],
];# config/packages/hugronaphor_circuit_breaker.yaml
hugronaphor_circuit_breaker:
storage: doctrine # or 'in_memory', 'dynamodb', or custom service ID
default_failure_threshold: 3
default_recovery_timeout: 60# config/packages/doctrine.yaml
doctrine:
orm:
mappings:
HugronaphorCircuitBreaker:
type: attribute
dir: '%kernel.project_dir%/vendor/hugronaphor/circuit-breaker/src/Bridge/Doctrine/Entity'
prefix: 'Hugronaphor\CircuitBreaker\Bridge\Doctrine\Entity'
alias: HugronaphorCircuitBreaker
is_bundle: falseThen run migrations:
php bin/console make:migration
php bin/console doctrine:migrations:migrateuse Hugronaphor\CircuitBreaker\CircuitBreakerFactory;
class ExchangeRateService
{
public function __construct(
private readonly CircuitBreakerFactory $circuitBreakerFactory,
) {}
public function getRate(string $from, string $to): float
{
return $this->circuitBreakerFactory->create('exchange_rate_api')
->call(
operation: fn() => $this->apiClient->fetchRate($from, $to),
fallback: fn() => $this->getCachedRate($from, $to),
);
}
}| Backend | Use Case | Config |
|---|---|---|
InMemoryStorage |
Testing, single-process apps | storage: in_memory |
DoctrineCircuitBreakerStorage |
Multi-process apps, traditional hosting | storage: doctrine |
DynamoDbCircuitBreakerStorage |
AWS Lambda, serverless | storage: dynamodb |
Custom storage can be implemented via CircuitBreakerStorageInterface.
Increase failureThreshold:
$factory->create('flaky_api', failureThreshold: 10);Decrease recoveryTimeoutSeconds or manually reset:
$circuitBreaker->reset();Switch from InMemoryStorage to DynamoDbStorage or DoctrineStorage.
Ensure the mapping is added to doctrine.yaml. For multiple entity managers, place it under doctrine.orm.entity_managers.<manager_name>.mappings.
For detailed documentation including:
- Full API reference
- All storage backend configurations
- Real-world examples
- Best practices
- Monitoring & observability
See docs/llms.txt.
MIT