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

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

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

  [ home ](https://www.msaied.com)    [ articles ](https://www.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%2Fwww.msaied.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%2Fwww.msaied.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://www.msaied.com/articles) 

 [ ![Laravel Telescope Alternatives: Building a Lightweight Request Inspector with Middleware](https://cdn.msaied.com/216/9b6d240010b80483f072902dafcd216c.png) laravel middleware debugging 

### Laravel Telescope Alternatives: Building a Lightweight Request Inspector with Middleware

Telescope is powerful but heavy for production. Learn how to build a focused, low-overhead request inspector u...

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

 16 Jun 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-telescope-alternatives-building-a-lightweight-request-inspector-with-middleware) [ ![RAG Pipelines in Laravel: Chunking, Embedding, and Retrieval with pgvector](https://cdn.msaied.com/215/e037e13535aa77822f879ee829ec3f68.png) laravel ai pgvector 

### RAG Pipelines in Laravel: Chunking, Embedding, and Retrieval with pgvector

Build a production-ready Retrieval-Augmented Generation pipeline in Laravel using pgvector, OpenAI embeddings,...

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

 16 Jun 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/rag-pipelines-in-laravel-chunking-embedding-and-retrieval-with-pgvector) [ ![Laravel Pest: Architecture Tests, Mutation Testing, and Type Coverage in CI](https://cdn.msaied.com/214/0d4822fa8ee1765d0689e387dd849d92.png) laravel pest testing 

### Laravel Pest: Architecture Tests, Mutation Testing, and Type Coverage in CI

Go beyond feature tests. Learn how to enforce architectural rules, catch logic gaps with mutation testing, and...

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

 16 Jun 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-pest-architecture-tests-mutation-testing-and-type-coverage-in-ci) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.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://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.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)
