Laravel Octane: Worker Lifecycle &amp; Memory Leaks | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Laravel Octane Worker Lifecycle, State Leakage, and Memory Management

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

 Octane keeps workers alive between requests, which means singleton state, static properties, and unbounded caches can silently corrupt responses. Learn how to reason about worker memory and write leak-proof code.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 15 Jun 2026 · Updated 15 Jun 2026 · 3 min read

ShareCopy linkCopied

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

  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)

 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.

- [laravel](https://www.msaied.com/public/articles?search=laravel)
- [octane](https://www.msaied.com/public/articles?search=octane)
- [performance](https://www.msaied.com/public/articles?search=performance)
- [php](https://www.msaied.com/public/articles?search=php)

 Frequently asked questions 
---------------------------

  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.

   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.

   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.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

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

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleFilament v3 Testing with Pest: Resources, Actions, and Form Assertions](https://www.msaied.com/public/articles/filament-v3-testing-with-pest-resources-actions-and-form-assertions) [Next articleFilament v4 Custom Field Plugins: Building Reusable Schema Components](https://www.msaied.com/public/articles/filament-v4-custom-field-plugins-building-reusable-schema-components)  

   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)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
