PHPackages                             bottledcode/durable-php - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. bottledcode/durable-php

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

bottledcode/durable-php
=======================

v2.2.3(11mo ago)11428[1 issues](https://github.com/bottledcode/durable-php/issues)[13 PRs](https://github.com/bottledcode/durable-php/pulls)MITPHPPHP &gt;=8.4CI passing

Since Jan 14Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/bottledcode/durable-php)[ Packagist](https://packagist.org/packages/bottledcode/durable-php)[ RSS](/packages/bottledcode-durable-php/feed)WikiDiscussions v2 Synced today

READMEChangelog (10)Dependencies (16)Versions (34)Used By (0)

Durable PHP
===========

[](#durable-php)

This is a framework/library to allow building global, distributed, and durable PHP applications. It is inspired by several Microsoft projects:

1. [Orleans](https://dotnet.github.io/orleans/)
2. [Service Fabric](https://docs.microsoft.com/en-us/azure/service-fabric/)
3. [Durable Functions](https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview)
4. [Dapr](https://dapr.io/)

Along with Akka, Erlang, and other actor-based frameworks.

What is it?
-----------

[](#what-is-it)

Durable PHP is a framework/library that allows you to build distributed applications that are durable. Durable means that the application can survive failures of individual components, and that the application can be scaled up and down without any downtime. Durable PHP uses RethinkDb or Redis as the underlying storage.

How does it work?
-----------------

[](#how-does-it-work)

The building blocks of Durable PHP are called 'Activities'. An Activity is a stateless class implementing a single method or callable. Activities are allowed to call other activities, compute, perform I/O, and wait for events. Activities are executed by a worker process. The worker process is responsible for executing the activities and storing the state of the activities in the database.

'Orchestrations' are built on top of Activities. An orchestration is a stateful class or method that can call other orchestrations and activities. The state of an orchestration is stored in the database and the state is recreated by ' replaying' the orchestration. Thus, I/O is not recommended for orchestrations, as it will be executed multiple times.

'Actors' are built on top of Orchestrations. An actor is a stateful class or method that can call other actors, perform I/O and wait for events. The state of an actor is stored in the database and the state is recreated by hydrating the actor.

How is this different from regular PHP?
---------------------------------------

[](#how-is-this-different-from-regular-php)

Regular PHP is stateless. This means that every request is handled by a new PHP process. This is great for performance and scalability, but it makes it hard to build applications that need to maintain state -- usually involving ORMs and ceremonies to load state. Durable PHP allows you to build applications that maintain state, and that can survive failures of individual components. Durable PHP is also designed to be used in a distributed environment, where multiple PHP processes are running on different machines without deadlocks.

How is this different from other PHP frameworks?
------------------------------------------------

[](#how-is-this-different-from-other-php-frameworks)

Durable PHP encourages rich models and domain-driven design (DDD). This means that you can build your application using classes and methods that represent your domain.

Can I see an example?
---------------------

[](#can-i-see-an-example)

Imagine you want upload a file to S3 and wait for the file to be processed, then send an email to the user or an email to the admin if something went wrong or it took to long. Without Durable-PHP, this would be quite complex. Here's what it looks like with Durable-PHP:

```
# SendEmailActivity.php

class SendEmailActivity {
    public function __invoke(string $to, string $subject, string $body) {
        // Send email
    }
}

# UploadEntityInterface.php

interface UploadEntityInterface {
    public function getFileUrl(): string;
    public function setProcessState(string $state): void;
    public function getProcessState(): string;
}

# UploadEntity.php

class UploadEntity extends \Bottledcode\DurablePhp\State\EntityState implements UploadEntityInterface {
    public function __construct(private string $url, private string $state = 'pending') {}
    public function setProcessState(string $state): void {
        $this->state = $state;
    }
    public function getProcessState(): string {
        return $this->state;
    }
}

# UploadOrchestration.php

class UploadOrchestration {
    public function __construct(private \Bottledcode\DurablePhp\OrchestrationContextInterface $context) {}

    public function __invoke(string $url) {
        $ctx = $this->context();
        $uploadId = $ctx->newUuid();

        // get a future that will be resolved when the upload is processed
        $signal = $context->waitForExternalEvent('upload-processed');

        // get a future that will be resolved when the timer expires (one hour from now)
        $timeout = $context->createTimer($context->getCurrentTime()->add(new DateInterval('PT1H')))

        // wait for the upload to be processed or the timer to expire
        $winner = $context->waitAny($signal, $timeout);

        if($winner === $signal) {
            // upload was processed
            $ctx->signal($uploadId, fn(UploadEntity $entity) => $entity->setProcessState('processed'));
            $context->callActivity(SendEmailActivity::class, ['to' => 'user', 'subject' => 'Upload processed', 'body' => 'Your upload was processed']);
        } else {
            // upload was not processed
            $ctx->signal($uploadId, fn(UploadEntity $entity) => $entity->setProcessState('timed-out'));
            $context->callActivity(SendEmailActivity::class, ['to' => 'admin', 'subject' => 'Upload failed', 'body' => 'The upload timed out']);
        }
    }
}
```

How do I use it?
----------------

[](#how-do-i-use-it)

This is nowhere near production ready, so if you want to use it, be prepared for things to be broken or change drastically without much warning. If you are using this though, please let me know in the issues. I'd love to hear about it and what you are using it for.

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance61

Regular maintenance activity

Popularity19

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity71

Established project with proven stability

 Bus Factor1

Top contributor holds 83.5% 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 ~36 days

Recently: every ~1 days

Total

16

Last Release

330d ago

PHP version history (2 changes)v2.0.0-rc1PHP &gt;=8.3

v2.1.0PHP &gt;=8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1883296?v=4)[Rob Landers](/maintainers/withinboredom)[@withinboredom](https://github.com/withinboredom)

---

Top Contributors

[![withinboredom](https://avatars.githubusercontent.com/u/1883296?v=4)](https://github.com/withinboredom "withinboredom (324 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (64 commits)")

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/bottledcode-durable-php/health.svg)

```
[![Health](https://phpackages.com/badges/bottledcode-durable-php/health.svg)](https://phpackages.com/packages/bottledcode-durable-php)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k95.4M306](/packages/laravel-horizon)[danog/madelineproto

Async PHP client API for the telegram MTProto protocol.

3.5k902.0k23](/packages/danog-madelineproto)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M345](/packages/psalm-plugin-laravel)[drupal-code-builder/drupal-code-builder

Code generator for Drupal

27253.3k1](/packages/drupal-code-builder-drupal-code-builder)[bowphp/framework

The bow PHP Framework

6017.5k13](/packages/bowphp-framework)

PHPackages © 2026

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