PHPackages                             utopia-php/circuit-breaker - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. utopia-php/circuit-breaker

ActiveLibrary[Framework](/categories/framework)

utopia-php/circuit-breaker
==========================

Light &amp; simple Circuit Breaker for PHP to prevent cascading failures in distributed systems.

0.3.1(1w ago)010.3k↑41.1%1MITPHPPHP &gt;=8.2CI passing

Since Apr 22Pushed 1w agoCompare

[ Source](https://github.com/utopia-php/circuit-breaker)[ Packagist](https://packagist.org/packages/utopia-php/circuit-breaker)[ RSS](/packages/utopia-php-circuit-breaker/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (4)Versions (7)Used By (1)

Utopia Circuit Breaker
======================

[](#utopia-circuit-breaker)

[![Build Status](https://github.com/utopia-php/circuit-breaker/actions/workflows/tests.yml/badge.svg)](https://github.com/utopia-php/circuit-breaker/actions/workflows/tests.yml)[![Total Downloads](https://camo.githubusercontent.com/7ea4fdd1ae162a3c78092f9f47f1d5fcac2a18032f8c55e318b090d8adba8e90/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f75746f7069612d7068702f636972637569742d627265616b65722e737667)](https://camo.githubusercontent.com/7ea4fdd1ae162a3c78092f9f47f1d5fcac2a18032f8c55e318b090d8adba8e90/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f75746f7069612d7068702f636972637569742d627265616b65722e737667)[![Discord](https://camo.githubusercontent.com/6e418910df1b6eb524c6cbd88dbaf5a5aa294316eeadcd963e11262a319f6321/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3536343136303733303834353135313234343f6c6162656c3d646973636f7264)](https://appwrite.io/discord)

Utopia Circuit Breaker is a simple and lite library for protecting PHP applications from cascading failures when a downstream dependency misbehaves. The breaker tracks failures, short-circuits calls when a service is unhealthy, and gradually probes recovery — with optional shared state (Redis / Swoole Table) and native telemetry via [`utopia-php/telemetry`](https://github.com/utopia-php/telemetry). This library is aiming to be as simple and easy to learn and use. This library is maintained by the [Appwrite team](https://appwrite.io).

Although this library is part of the [Utopia Framework](https://github.com/utopia-php/framework) project it is dependency free and can be used as standalone with any other PHP project or framework.

Getting Started
---------------

[](#getting-started)

Install using composer:

```
composer require utopia-php/circuit-breaker
```

Init in your PHP code:

```
require_once __DIR__ . '/vendor/autoload.php';

use Utopia\CircuitBreaker\CircuitBreaker;

$breaker = new CircuitBreaker(
    threshold: 3,         // Open circuit after 3 failures
    timeout: 30,          // Try half-open after 30 seconds
    successThreshold: 2   // Require 2 successes to close circuit
);

$result = $breaker->call(
    open: fn () => 'Service unavailable - circuit is open',
    close: fn () => makeExternalApiCall(),
    halfOpen: fn () => makeExternalApiCall() // Optional: called during recovery testing
);
```

How it Works
------------

[](#how-it-works)

The circuit breaker operates in three states:

1. **CLOSED** (normal operation) — calls pass through to the protected service. Failures are counted; once they reach `threshold`, the circuit transitions to **OPEN**.
2. **OPEN** (blocking) — calls are immediately short-circuited to the `open` callback (your fallback). After `timeout` seconds the circuit transitions to **HALF\_OPEN**.
3. **HALF\_OPEN** (probing recovery) — the next calls execute the `halfOpen` callback (or `close` if not provided). After `successThreshold` consecutive successes the circuit transitions back to **CLOSED**; any failure immediately re-opens it.

The optional `halfOpen` callback lets you apply different behaviour while probing (shorter timeouts, smaller payloads, extra logging).

Examples
--------

[](#examples)

### Using all three states

[](#using-all-three-states)

```
use Utopia\CircuitBreaker\CircuitBreaker;

$breaker = new CircuitBreaker(threshold: 3, timeout: 30, successThreshold: 2);

$result = $breaker->call(
    open: function () {
        // Circuit is OPEN — service is down
        logger()->warning('Circuit breaker is OPEN - using fallback');
        return getCachedData() ?? ['error' => 'Service unavailable'];
    },
    close: function () {
        // Circuit is CLOSED — normal operation
        return apiClient()->fetchData();
    },
    halfOpen: function () {
        // Circuit is HALF_OPEN — testing recovery
        logger()->info('Circuit breaker testing recovery...');
        return apiClient()->fetchData(['timeout' => 5]);
    }
);
```

### Wrapping a real HTTP call

[](#wrapping-a-real-http-call)

```
use Utopia\CircuitBreaker\CircuitBreaker;

$breaker = new CircuitBreaker(threshold: 5, timeout: 60, successThreshold: 2);

$data = $breaker->call(
    open: fn () => cache()->get('user_data') ?? ['error' => 'Service temporarily unavailable'],
    close: function () {
        $response = Http::get('https://api.example.com/users');

        if (!$response->successful()) {
            throw new \Exception('API request failed');
        }

        return $response->json();
    }
);
```

### Shared cache state

[](#shared-cache-state)

By default, each `CircuitBreaker` instance keeps state in memory. To share circuit state between PHP workers, pass a cache adapter and a stable `key`.

#### Redis

[](#redis)

```
use Utopia\CircuitBreaker\Adapter\Redis as RedisAdapter;
use Utopia\CircuitBreaker\CircuitBreaker;

$redis = new \Redis();
$redis->connect('127.0.0.1');

$breaker = new CircuitBreaker(
    threshold: 5,
    timeout: 60,
    successThreshold: 2,
    cache: new RedisAdapter($redis),
    key: 'users-api'
);
```

#### Swoole Table

[](#swoole-table)

Use the Swoole adapter when workers need to share state through Swoole shared memory.

```
use Utopia\CircuitBreaker\Adapter\SwooleTable;
use Utopia\CircuitBreaker\CircuitBreaker;

$table = SwooleTable::createTable(size: 1024);
$cache = new SwooleTable($table);

$breaker = new CircuitBreaker(
    threshold: 5,
    timeout: 60,
    successThreshold: 2,
    cache: $cache,
    key: 'users-api'
);
```

### Telemetry

[](#telemetry)

Telemetry is opt-in. The `telemetry` constructor argument defaults to `null`, which emits no metrics and does not require `utopia-php/telemetry` at runtime. Install `utopia-php/telemetry` and pass any adapter to emit counters and gauges for calls, fallbacks, callback failures, transitions, state, failure counts, success counts, active calls, and transition/probe events.

```
composer require utopia-php/telemetry
```

```
use Utopia\CircuitBreaker\CircuitBreaker;
use Utopia\Telemetry\Adapter\OpenTelemetry;

$telemetry = new OpenTelemetry(
    'http://otel-collector:4318/v1/metrics',
    'backend',
    'orders',
    gethostname() ?: 'local'
);

$breaker = new CircuitBreaker(
    threshold: 5,
    timeout: 60,
    successThreshold: 2,
    key: 'orders-api',
    telemetry: $telemetry,
    metricPrefix: 'backend'
);

$result = $breaker->call(
    open: fn () => ['fallback' => true],
    close: fn () => $client->request('/orders')
);

$telemetry->collect();
```

By default, metrics are emitted as `breaker.*`. Pass `metricPrefix` to namespace those metric names for a host application; for example `metricPrefix: 'backend'` emits `backend.breaker.calls`.

You can also attach or replace the adapter after construction:

```
$breaker = new CircuitBreaker(metricPrefix: 'backend');
$breaker->setTelemetry($telemetry);
```

API
---

[](#api)

### Constructor parameters

[](#constructor-parameters)

- `threshold` (int, default `3`) — failures tolerated before opening the circuit
- `timeout` (int, default `30`) — seconds to wait before transitioning to half-open
- `successThreshold` (int, default `2`) — consecutive half-open successes required to close
- `cache` (`?Utopia\CircuitBreaker\Adapter`, default `null`) — optional shared cache adapter
- `key` (string, default `default`) — cache namespace for one circuit's state
- `telemetry` (`?Utopia\Telemetry\Adapter`, default `null`) — optional telemetry adapter
- `metricPrefix` (string, default `''`) — optional prefix for telemetry metric names (e.g. `edge`)

### `call()` parameters

[](#call-parameters)

```
$breaker->call(
    open: callable,      // Required: Called when circuit is OPEN
    close: callable,     // Required: Called when circuit is CLOSED (or HALF_OPEN if no halfOpen callback)
    halfOpen: ?callable  // Optional: Called when circuit is HALF_OPEN
);
```

### State inspection

[](#state-inspection)

```
$state = $breaker->getState();  // Utopia\CircuitBreaker\CircuitState enum

$breaker->isOpen();
$breaker->isClosed();
$breaker->isHalfOpen();

$breaker->getFailureCount();
$breaker->getSuccessCount();
```

System Requirements
-------------------

[](#system-requirements)

- PHP 8.2 or later
- Optional: `utopia-php/telemetry`, `ext-opentelemetry`, and `ext-protobuf` for OpenTelemetry metrics and the local telemetry demo
- Optional: `ext-redis` for `Utopia\CircuitBreaker\Adapter\Redis`
- Optional: `ext-swoole` for `Utopia\CircuitBreaker\Adapter\SwooleTable`

Tests
-----

[](#tests)

Unit tests avoid Redis and Swoole runtime dependencies:

```
composer test
```

E2E tests run Redis and a PHP runtime with the Redis/Swoole extensions through Docker:

```
composer test:e2e:docker
```

### Local telemetry demo

[](#local-telemetry-demo)

Start Redis, an instrumented PHP demo server, OpenTelemetry Collector, Prometheus, and Grafana:

```
composer telemetry:up
```

- Demo UI:
- Grafana:
- Prometheus:

Preview from a five-minute `checkout-api` scenario:

[![Circuit breaker telemetry dashboard](docs/images/telemetry-dashboard.png)](docs/images/telemetry-dashboard.png)

Populate the dashboard with the same scenario:

```
composer telemetry:scenario
```

Stop the stack and remove local volumes:

```
composer telemetry:down
```

Copyright and license
---------------------

[](#copyright-and-license)

The MIT License (MIT)

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance98

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 81.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~12 days

Total

4

Last Release

11d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/023f08a9df59f81cc4a04b1cebd20f45ede5db53ef2f9e9ad3d75f4c69be66b8?d=identicon)[eldadfux](/maintainers/eldadfux)

---

Top Contributors

[![ChiragAgg5k](https://avatars.githubusercontent.com/u/110609663?v=4)](https://github.com/ChiragAgg5k "ChiragAgg5k (9 commits)")[![abnegate](https://avatars.githubusercontent.com/u/5857008?v=4)](https://github.com/abnegate "abnegate (2 commits)")

---

Tags

phpframeworkcircuit breakerfault toleranceupfutopiaresilience

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/utopia-php-circuit-breaker/health.svg)

```
[![Health](https://phpackages.com/badges/utopia-php-circuit-breaker/health.svg)](https://phpackages.com/packages/utopia-php-circuit-breaker)
```

###  Alternatives

[utopia-php/database

A simple library to manage application persistence using multiple database adapters

74384.6k10](/packages/utopia-php-database)[utopia-php/domains

Utopia Domains library is simple and lite library for parsing web domains. This library is aiming to be as simple and easy to learn and use.

53660.1k16](/packages/utopia-php-domains)[utopia-php/cli

A simple CLI library to manage command line applications

42460.5k14](/packages/utopia-php-cli)[utopia-php/cache

A simple cache library to manage application cache storing, loading and purging

31447.6k15](/packages/utopia-php-cache)[utopia-php/storage

A simple Storage library to manage application storage

30277.2k9](/packages/utopia-php-storage)[utopia-php/system

A simple library for obtaining information about the host's system.

25290.5k25](/packages/utopia-php-system)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
