Laravel Octane FrankenPHP Safe Singleton Patterns | 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)    Laravel Octane + FrankenPHP: Shared State, Request Isolation, and Safe Singleton Patterns        On this page       1. [  The Problem With Long-Lived Workers ](#the-problem-with-long-lived-workers)
2. [  Scoped Bindings: The Right Tool ](#scoped-bindings-the-right-tool)
3. [  When scoped() Is Not Enough ](#when-codescopedcode-is-not-enough)
4. [  Flush Hooks for Third-Party Singletons ](#flush-hooks-for-third-party-singletons)
5. [  Detecting Leaks Before Production ](#detecting-leaks-before-production)
6. [  Safe Patterns at a Glance ](#safe-patterns-at-a-glance)
7. [  Takeaways ](#takeaways)

  ![Laravel Octane + FrankenPHP: Shared State, Request Isolation, and Safe Singleton Patterns](https://cdn.msaied.com/349/e8f1b783afac1995d090c041f705d8c5.png)

  #laravel   #octane   #frankenphp   #performance   #architecture  

 Laravel Octane + FrankenPHP: Shared State, Request Isolation, and Safe Singleton Patterns 
===========================================================================================

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

       Table of contents

1. [  01   The Problem With Long-Lived Workers  ](#the-problem-with-long-lived-workers)
2. [  02   Scoped Bindings: The Right Tool  ](#scoped-bindings-the-right-tool)
3. [  03   When scoped() Is Not Enough  ](#when-codescopedcode-is-not-enough)
4. [  04   Flush Hooks for Third-Party Singletons  ](#flush-hooks-for-third-party-singletons)
5. [  05   Detecting Leaks Before Production  ](#detecting-leaks-before-production)
6. [  06   Safe Patterns at a Glance  ](#safe-patterns-at-a-glance)
7. [  07   Takeaways  ](#takeaways)

 The Problem With Long-Lived Workers
-----------------------------------

Traditional PHP-FPM boots the framework on every request and discards everything afterward. Octane — whether backed by Swoole, RoadRunner, or FrankenPHP — keeps a single worker process alive across thousands of requests. That is the source of its speed advantage, and the source of its most subtle bugs.

When you bind a class as a singleton in a service provider, that instance persists for the lifetime of the worker. Any mutable state it holds bleeds from one request into the next.

```php
// AppServiceProvider.php — dangerous under Octane
$this->app->singleton(CartService::class, function () {
    return new CartService(); // holds $this->items = []
});

```

Request A adds items to the cart. Request B — from a completely different user — resolves the same `CartService` instance and sees Request A's items. This is a classic Octane state-leak.

Scoped Bindings: The Right Tool
-------------------------------

Laravel ships a first-class solution: `scoped()`. A scoped binding behaves like a singleton within a single request lifecycle, then is flushed automatically by Octane between requests.

```php
// Correct: scoped to one request
$this->app->scoped(CartService::class, function () {
    return new CartService();
});

```

Octane calls `$app->forgetScopedInstances()` at the end of every request, so the next request gets a fresh instance. No manual cleanup required.

### When `scoped()` Is Not Enough

Some objects are legitimately shared across requests — database connection pools, compiled route collections, config repositories. The rule of thumb:

- **Stateless or immutable** → `singleton()` is fine.
- **Mutable, request-specific** → use `scoped()`.
- **Mutable, shared intentionally** → use `singleton()` but make mutation thread-safe (Swoole) or accept that FrankenPHP workers are isolated processes.

FrankenPHP's worker mode uses separate PHP fibers per request within the same process, so true shared memory between concurrent requests is not a concern the way it is with Swoole coroutines. However, sequential requests in the same worker still share the same singleton instances.

Flush Hooks for Third-Party Singletons
--------------------------------------

You do not always control whether a package registers a singleton or a scoped binding. Octane provides flush hooks to reset specific instances between requests.

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

```

For more granular control, listen to the `RequestReceived` and `RequestTerminated` Octane events:

```php
use Laravel\Octane\Events\RequestReceived;
use Laravel\Octane\Events\RequestTerminated;

Event::listen(RequestReceived::class, function ($event) {
    $event->sandbox->forgetInstance(ReportBuilder::class);
});

```

`$event->sandbox` is the per-request application clone Octane creates — mutating it does not affect the master container.

Detecting Leaks Before Production
---------------------------------

Octane ships with a `--watch` flag for development, but it will not surface state leaks automatically. A practical detection pattern is to inject a unique request ID into any suspicious singleton and assert it changes between requests in a test:

```php
it('creates a fresh CartService per request', function () {
    $first = $this->get('/cart')->json('session_id');
    $second = $this->get('/cart')->json('session_id');

    expect($first)->not->toBe($second);
});

```

For deeper inspection, Telescope's request watcher combined with a custom `Octane:RequestTerminated` listener that dumps resolved instances is invaluable during staging.

Safe Patterns at a Glance
-------------------------

```php
// 1. Immutable value object — singleton is fine
$this->app->singleton(CurrencyFormatter::class);

// 2. Request-scoped accumulator — use scoped
$this->app->scoped(AuditLog::class);

// 3. External client with connection pool — singleton, but reset on error
$this->app->singleton(RedisClient::class, fn() => new RedisClient(config('redis')));

```

Takeaways
---------

- Use `scoped()` for any service that accumulates request-specific state; Octane flushes it automatically.
- `singleton()` is safe only for stateless or intentionally shared objects.
- FrankenPHP workers are isolated processes, not coroutines — concurrent request bleed is sequential, not parallel.
- Octane's `flush` config key and `RequestReceived` event are your escape hatches for third-party singletons.
- Write a simple request-ID test to catch leaks before they reach production.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-octane-frankenphp-shared-state-request-isolation-and-safe-singleton-patterns&text=Laravel+Octane+%2B+FrankenPHP%3A+Shared+State%2C+Request+Isolation%2C+and+Safe+Singleton+Patterns) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-octane-frankenphp-shared-state-request-isolation-and-safe-singleton-patterns) 

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

  3 questions  

     Q01  What is the difference between singleton() and scoped() in Laravel Octane?        A singleton() persists for the entire worker lifetime across all requests. A scoped() binding behaves like a singleton within a single request and is automatically flushed by Octane between requests, preventing state from leaking to the next user. 

      Q02  Does FrankenPHP have the same concurrency risks as Swoole coroutines?        No. FrankenPHP uses separate PHP fibers per request within a worker process, so concurrent requests do not share memory the way Swoole coroutines can. However, sequential requests in the same worker still share singleton instances, so scoped bindings are still essential. 

      Q03  How do I reset a third-party package's singleton between Octane requests?        Add the class to the flush array in config/octane.php, or listen to the Octane RequestReceived event and call $event-&gt;sandbox-&gt;forgetInstance(YourClass::class) to drop the instance before the next request resolves it. 

  Continue reading

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

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

 [ ![MySQL Index Strategies for Laravel: Composite, Prefix, and Invisible Indexes](https://cdn.msaied.com/350/912f5f70221bdcf02445affe13db6383.png) laravel mysql performance 

### MySQL Index Strategies for Laravel: Composite, Prefix, and Invisible Indexes

Beyond basic single-column indexes, MySQL offers composite, prefix, and invisible indexes that dramatically ch...

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

 3 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/mysql-index-strategies-for-laravel-composite-prefix-and-invisible-indexes) [ ![Commune: A Private Community for Laravel Founders and Builders](https://cdn.msaied.com/346/a188e82cf37740fad2be5b4f70efaad1.png) community founders indie makers 

### Commune: A Private Community for Laravel Founders and Builders

Commune is a private community built for founders, makers, and developers to share progress, get feedback, fin...

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

 2 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/commune-a-private-community-for-laravel-founders-and-builders) [ ![Laravel AI Tasks: AI Orchestration with Queues, Logging, and Cost Control](https://cdn.msaied.com/347/4274eb6d6025d184daaaba35cc79c1f9.png) Laravel AI Packages 

### Laravel AI Tasks: AI Orchestration with Queues, Logging, and Cost Control

Laravel AI Tasks is a package that wraps the Laravel AI SDK with reusable task classes, three execution modes,...

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

 2 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-ai-tasks-ai-orchestration-with-queues-logging-and-cost-control) 

   [  ![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)
