Laravel Octane: Worker Lifecycle &amp; Memory Leaks | 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 Worker Lifecycle, State Leakage, and Memory Management        On this page       1. [  Why Octane Changes Everything About State ](#why-octane-changes-everything-about-state)
2. [  The Worker Boot Sequence ](#the-worker-boot-sequence)
3. [  Common Leakage Patterns ](#common-leakage-patterns)
4. [  1. Singleton Accumulating State ](#1-singleton-accumulating-state)
5. [  2. Static Property Accumulation ](#2-static-property-accumulation)
6. [  3. Event Listener Duplication ](#3-event-listener-duplication)
7. [  Memory Profiling Under Octane ](#memory-profiling-under-octane)
8. [  Automatic Worker Recycling ](#automatic-worker-recycling)
9. [  Checklist Before Deploying to Octane ](#checklist-before-deploying-to-octane)
10. [  Key Takeaways ](#key-takeaways)

  ![Laravel Octane Worker Lifecycle, State Leakage, and Memory Management](https://cdn.msaied.com/178/ad8e002dedd4857edb32e66305f47498.png)

  #laravel   #octane   #performance   #php  

 Laravel Octane Worker Lifecycle, State Leakage, and Memory Management 
=======================================================================

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

       Table of contents

  10 sections  

1. [  01   Why Octane Changes Everything About State  ](#why-octane-changes-everything-about-state)
2. [  02   The Worker Boot Sequence  ](#the-worker-boot-sequence)
3. [  03   Common Leakage Patterns  ](#common-leakage-patterns)
4. [  04   1. Singleton Accumulating State  ](#1-singleton-accumulating-state)
5. [  05   2. Static Property Accumulation  ](#2-static-property-accumulation)
6. [  06   3. Event Listener Duplication  ](#3-event-listener-duplication)
7. [  07   Memory Profiling Under Octane  ](#memory-profiling-under-octane)
8. [  08   Automatic Worker Recycling  ](#automatic-worker-recycling)
9. [  09   Checklist Before Deploying to Octane  ](#checklist-before-deploying-to-octane)
10. [  10   Key Takeaways  ](#key-takeaways)

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

Traditional PHP-FPM resets the entire process between requests. Octane — whether backed by Swoole, RoadRunner, or FrankenPHP — keeps a single worker alive for thousands of requests. The application is booted once; the service container, bound singletons, and static class properties all persist.

This is the source of Octane's speed. It is also the source of its most subtle bugs.

---

The Worker Boot Sequence
------------------------

When Octane starts, each worker:

1. Boots the Laravel application (`Application::boot()`).
2. Resolves all `singleton` bindings registered in service providers.
3. Enters a request loop, calling `Application::resetScope()` between requests.

`resetScope()` re-binds a small set of request-scoped services (`Request`, `Auth`, `Session`, etc.) but it does **not** re-instantiate your own singletons.

```php
// config/octane.php
'warm' => [
    ...Octane::defaultServicesToWarm(),
    App\Services\CurrencyConverter::class, // pre-resolved on boot
],

'flush' => [
    App\Services\ReportCache::class, // re-resolved every request
],

```

Services in `warm` are resolved once. Services in `flush` are discarded and re-resolved on every request — use `flush` for anything that holds per-request state.

---

Common Leakage Patterns
-----------------------

### 1. Singleton Accumulating State

```php
class NotificationAggregator
{
    private array $pending = [];

    public function push(Notification $n): void
    {
        $this->pending[] = $n; // grows forever across requests
    }
}

```

Fix: implement `OctaneAware` and reset in `flush`, or make the class request-scoped via `$this->app->scoped()`.

```php
// AppServiceProvider
$this->app->scoped(NotificationAggregator::class);

```

`scoped()` behaves like `singleton` within a single request and is automatically re-bound by Octane's scope reset.

### 2. Static Property Accumulation

```php
class QueryLogger
{
    public static array $log = [];

    public static function record(string $sql): void
    {
        self::$log[] = $sql; // never cleared
    }
}

```

Static properties are invisible to the container. Register an Octane request listener to reset them:

```php
// OctaneServiceProvider
Octane::tick('request-reset', function () {
    QueryLogger::$log = [];
});

```

Or better: avoid mutable statics entirely and route state through a scoped service.

### 3. Event Listener Duplication

If you call `Event::listen()` inside a request handler or a middleware that runs on every request, listeners stack up on the same dispatcher instance:

```php
// BAD — called on every request inside a middleware
Event::listen(OrderPlaced::class, SendConfirmation::class);

```

Listeners should be registered once in a service provider, never inside the request path.

---

Memory Profiling Under Octane
-----------------------------

Octane exposes worker memory via its status command:

```bash
php artisan octane:status

```

For deeper profiling, instrument the `RequestHandled` event:

```php
Event::listen(RequestHandled::class, function (RequestHandled $event) {
    $mb = round(memory_get_usage(true) / 1048576, 2);
    logger()->channel('octane')->info("Memory: {$mb} MB", [
        'url' => $event->request->url(),
    ]);
});

```

Watch for monotonically increasing memory across requests on the same worker. A flat or oscillating line is healthy; a rising line indicates a leak.

### Automatic Worker Recycling

As a safety net, configure `max_requests` to recycle workers after a fixed number of requests:

```php
// config/octane.php
'swoole' => [
    'options' => [
        'max_request' => 500,
    ],
],

```

This is not a substitute for fixing leaks — it is a circuit breaker that bounds worst-case memory growth.

---

Checklist Before Deploying to Octane
------------------------------------

- **Audit every singleton** for mutable instance state.
- **Replace mutable statics** with scoped container bindings.
- **Move per-request state** to `scoped()` or `flush`.
- **Never register listeners inside the request path.**
- **Set `max_requests`** as a safety net, not a primary fix.
- **Log memory per request** in staging before going live.

---

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

- Octane's speed comes from a persistent worker; that same persistence is the root of all state bugs.
- `scoped()` is the correct tool for per-request singletons — prefer it over `singleton` for stateful services.
- Static properties bypass the container and must be reset manually via Octane listeners.
- Memory profiling via `RequestHandled` events catches leaks before they reach production.
- `max_requests` recycling is a circuit breaker, not a fix.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-octane-worker-lifecycle-state-leakage-and-memory-management&text=Laravel+Octane+Worker+Lifecycle%2C+State+Leakage%2C+and+Memory+Management) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Flaravel-octane-worker-lifecycle-state-leakage-and-memory-management) 

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

  3 questions  

     Q01  What is the difference between `singleton()` and `scoped()` in Octane?        `singleton()` resolves once per worker lifetime and persists across all requests. `scoped()` resolves once per request — Octane's scope reset discards and re-resolves it at the start of each new request, making it safe for stateful per-request services. 

      Q02  Does Octane's `flush` array fully prevent memory leaks?        It re-resolves listed services each request, which prevents state accumulation in those bindings. However, static class properties, event listener duplication, and third-party packages that use statics are not covered — those require explicit reset logic or architectural changes. 

      Q03  Can I use Laravel Octane with packages that were not written with it in mind?        Often yes, but you must audit the package for mutable singletons and static state. Many popular packages are already Octane-compatible. For those that are not, wrapping their state in a `flush`-listed adapter or resetting them via an `RequestReceived` listener is the standard approach. 

  Continue reading

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

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

 [ ![Laravel Gates, Policies, and Response-Based Access Control in Depth](https://cdn.msaied.com/181/5bda736cd48ab747366fdac25d0d0d78.png) laravel authorization security 

### Laravel Gates, Policies, and Response-Based Access Control in Depth

Move beyond simple boolean gates. Learn how Laravel's Response objects, before hooks, policy filters, and inli...

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

 15 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/laravel-gates-policies-and-response-based-access-control-in-depth) [ ![Laravel Reverb in Production: Scaling WebSockets Beyond a Single Server](https://cdn.msaied.com/180/b3f362d3b1f7da03af9a87a26ffcbdf6.png) laravel reverb websockets 

### Laravel Reverb in Production: Scaling WebSockets Beyond a Single Server

Reverb ships as a first-party WebSocket server for Laravel, but running it on a single node won't cut it under...

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

 15 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/laravel-reverb-in-production-scaling-websockets-beyond-a-single-server) [ ![Filament v4 Custom Field Plugins: Building Reusable Schema Components](https://cdn.msaied.com/179/3d535cc5bcced4a170d41e383ab06883.png) filament laravel filament-v4 

### Filament v4 Custom Field Plugins: Building Reusable Schema Components

Learn how to build a distributable Filament v4 custom field plugin using the unified Schema API, auto-discover...

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

 15 Jun 2026     1 min read  

  Read    

 ](https://msaied.com/articles/filament-v4-custom-field-plugins-building-reusable-schema-components) 

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