Laravel Octane: Worker Lifecycle &amp; Safe Singletons | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Octane Worker Lifecycle, State Leakage, and Safe Singleton Patterns in Laravel        On this page       1. [  Why Octane Changes Everything About Application State ](#why-octane-changes-everything-about-application-state)
2. [  The Worker Lifecycle in Three Phases ](#the-worker-lifecycle-in-three-phases)
3. [  Where State Leakage Actually Happens ](#where-state-leakage-actually-happens)
4. [  1. Mutable Singleton Properties ](#1-mutable-singleton-properties)
5. [  2. Static Properties ](#2-static-properties)
6. [  3. Closures Capturing Request-Scoped Objects ](#3-closures-capturing-request-scoped-objects)
7. [  The Octane Reset Hook ](#the-octane-reset-hook)
8. [  Writing Genuinely Safe Singletons ](#writing-genuinely-safe-singletons)
9. [  Detecting Leakage Before Production ](#detecting-leakage-before-production)
10. [  Key Takeaways ](#key-takeaways)

  ![Octane Worker Lifecycle, State Leakage, and Safe Singleton Patterns in Laravel](https://cdn.msaied.com/370/4281f7f24283d53ad4c1e162c905cf2b.png)

  #laravel   #octane   #performance   #architecture  

 Octane Worker Lifecycle, State Leakage, and Safe Singleton Patterns in Laravel 
================================================================================

     5 Jul 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  10 sections  

1. [  01   Why Octane Changes Everything About Application State  ](#why-octane-changes-everything-about-application-state)
2. [  02   The Worker Lifecycle in Three Phases  ](#the-worker-lifecycle-in-three-phases)
3. [  03   Where State Leakage Actually Happens  ](#where-state-leakage-actually-happens)
4. [  04   1. Mutable Singleton Properties  ](#1-mutable-singleton-properties)
5. [  05   2. Static Properties  ](#2-static-properties)
6. [  06   3. Closures Capturing Request-Scoped Objects  ](#3-closures-capturing-request-scoped-objects)
7. [  07   The Octane Reset Hook  ](#the-octane-reset-hook)
8. [  08   Writing Genuinely Safe Singletons  ](#writing-genuinely-safe-singletons)
9. [  09   Detecting Leakage Before Production  ](#detecting-leakage-before-production)
10. [  10   Key Takeaways  ](#key-takeaways)

       Why Octane Changes Everything About Application State
-----------------------------------------------------

Traditional PHP-FPM boots a fresh process per request. Laravel Octane — whether backed by Swoole, RoadRunner, or FrankenPHP — keeps a single worker alive and serves thousands of requests through it. Boot time drops dramatically, but the trade-off is brutal: **anything bound as a singleton in the service container persists across requests unless you explicitly flush it**.

Understanding the worker lifecycle is the first step to writing Octane-safe code.

The Worker Lifecycle in Three Phases
------------------------------------

```php
Boot phase      → app()->boot(), all providers registered, singletons created
Request phase   → clone of the app (sandbox) handles the request
Reset phase     → sandbox discarded, base app state partially restored

```

Octane creates a **sandbox** — a shallow clone of the application container — for each request. Bindings marked as singletons in the base app are **not** re-instantiated; the same object is handed to every sandbox. That is the leakage vector.

Where State Leakage Actually Happens
------------------------------------

### 1. Mutable Singleton Properties

```php
class CartService
{
    private array $items = [];

    public function add(int $productId): void
    {
        $this->items[] = $productId;
    }

    public function all(): array
    {
        return $this->items;
    }
}

```

Bound as a singleton, `$items` accumulates across every request in the same worker. User A's cart bleeds into User B's.

### 2. Static Properties

Static properties are not scoped to the container at all — they live on the class itself and survive every request, every sandbox, every flush.

```php
class FeatureFlags
{
    private static array $resolved = [];
    // Never safe to cache per-request data here under Octane
}

```

### 3. Closures Capturing Request-Scoped Objects

A service provider that captures `$request` or `Auth::user()` inside a closure at boot time will freeze that value for the worker's lifetime.

The Octane Reset Hook
---------------------

Octane fires `Illuminate\Foundation\Events\RequestHandled` and exposes a dedicated `octane:request-handled` hook. The cleaner API is the `OctaneServiceProvider`:

```php
use Laravel\Octane\Facades\Octane;

class CartServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Octane::tick('flush-cart', function () {
            // runs between requests — avoid heavy work here
        });

        $this->callAfterResolving(CartService::class, function (CartService $service) {
            // not useful for reset; use the listener below
        });
    }
}

```

The correct approach is registering a listener on `RequestHandled` or using Octane's `flush` list:

```php
// config/octane.php
'flush' => [
    \App\Services\CartService::class,
],

```

Octane calls `flush()` on each listed class after every request. Implement the interface:

```php
use Laravel\Octane\Contracts\ServesStaticFiles; // wrong example
// Octane checks for a flush() method via duck-typing

class CartService
{
    private array $items = [];

    public function flush(): void
    {
        $this->items = [];
    }
}

```

Writing Genuinely Safe Singletons
---------------------------------

The safest pattern is **immutable singletons** — services that hold only configuration or collaborators, never per-request data.

```php
class PricingEngine
{
    public function __construct(
        private readonly TaxRateRepository $taxes,
        private readonly CurrencyConverter $converter,
    ) {}

    public function calculate(Money $amount, string $currency): Money
    {
        // Pure computation; no state stored on $this
        return $this->converter->convert(
            $amount->add($this->taxes->rateFor($currency)),
            $currency,
        );
    }
}

```

When you genuinely need per-request state, **bind it scoped** rather than as a singleton:

```php
$this->app->scoped(CartService::class, fn () => new CartService());

```

`scoped()` behaves like a singleton within a single request sandbox but is re-instantiated for the next request — exactly the semantics you want under Octane.

Detecting Leakage Before Production
-----------------------------------

Run your test suite with Octane's `--workers=1` flag and fire the same endpoint twice in the same worker process. A simple integration test:

```php
it('does not leak cart state between requests', function () {
    $this->post('/cart', ['product_id' => 1]);
    $this->post('/cart', ['product_id' => 2]);

    $response = $this->getJson('/cart');

    // Should contain only items from the current request session
    $response->assertJsonCount(1, 'data');
});

```

Pair this with Octane's built-in `octane:status` command and memory profiling to catch workers that grow unboundedly.

Key Takeaways
-------------

- Octane sandboxes clone the container but **share singleton instances** from the base app.
- Mutable singleton properties and static class properties are the two most common leakage sources.
- Use `scoped()` for per-request services; reserve `singleton()` for truly stateless collaborators.
- Register a `flush()` method and add the class to `config/octane.php flush` for services that must reset.
- Write immutable services by default — pure computation over stored state eliminates the problem entirely.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Foctane-worker-lifecycle-state-leakage-and-safe-singleton-patterns-in-laravel&text=Octane+Worker+Lifecycle%2C+State+Leakage%2C+and+Safe+Singleton+Patterns+in+Laravel) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Foctane-worker-lifecycle-state-leakage-and-safe-singleton-patterns-in-laravel) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  What is the difference between singleton() and scoped() in Laravel Octane?        singleton() creates one instance for the entire worker lifetime, shared across all requests. scoped() creates one instance per request sandbox and is discarded after each request completes, making it safe for per-request state under Octane. 

      Q02  Does the Octane flush list work with RoadRunner as well as Swoole?        Yes. The flush mechanism is implemented at the Octane layer, not the server driver layer. Any class listed in config/octane.php under 'flush' will have its flush() method called between requests regardless of whether you use Swoole, RoadRunner, or FrankenPHP. 

      Q03  Are static properties automatically reset between Octane requests?        No. Static properties live on the class itself and are completely outside the container's scope. Octane has no mechanism to reset them automatically. You must reset static state manually in a RequestHandled listener or avoid static mutable state entirely. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Domain-Driven Design in Laravel: Value Objects, DTOs, and Actions Without Bloat](https://cdn.msaied.com/377/b5c2aef77aed51ee8694f377085af424.png) laravel ddd architecture 

### Domain-Driven Design in Laravel: Value Objects, DTOs, and Actions Without Bloat

Learn how to model domain concepts with value objects, DTOs, and single-action classes in Laravel — keeping yo...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 6 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/domain-driven-design-in-laravel-value-objects-dtos-and-actions-without-bloat) [ ![What's Missing from Your PHP Development Environment: Meet DDLess](https://cdn.msaied.com/379/baa8990d4c7b46d18498d69d68f9b6d2.png) DDLess PHP Debugging Laravel Tools 

### What's Missing from Your PHP Development Environment: Meet DDLess

DDLess is a PHP development workbench that brings step debugging, an in-breakpoint playground, and an interact...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 6 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/whats-missing-from-your-php-development-environment-meet-ddless) [ ![CQRS in Laravel Without a Framework: Commands, Handlers, and Query Objects](https://cdn.msaied.com/376/bec9da4b7a7ddeee26dac3df6f5d6c44.png) laravel cqrs architecture 

### CQRS in Laravel Without a Framework: Commands, Handlers, and Query Objects

Skip the heavy CQRS libraries. Learn how to implement commands, command handlers, and query objects in plain L...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 6 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/cqrs-in-laravel-without-a-framework-commands-handlers-and-query-objects) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
