Portfolio ©2026Loading experience
Design.Engineer.Ship.
Laravel × React × WebGL000
twogoodson ©
← All notes

What a year of Laravel Octane in production taught me

Memory leaks, state bleeding between requests, and why not every service provider should boot once.

Written by

TubagusFull Stack Developer

Published

Reading

7 min

Octane makes Laravel fast by keeping the application in memory between requests. That is also exactly what makes it dangerous: anything you used to treat as request-scoped is now potentially process-scoped.

The leak that took a week to find

Our worker memory crept up by ~2 MB per thousand requests. The culprit was a singleton that cached the authenticated user:

$this->app->singleton(CurrentTenant::class, function ($app) {
    return new CurrentTenant($app['request']->user());
});

On a classic PHP-FPM setup this is harmless. Under Octane, the first request's user sticks around for every request that worker serves afterwards.

What we changed

  • Moved request-bound services to scoped() bindings instead of singleton().
  • Added the class to Octane's flush list where a rebind wasn't possible.
  • Ran a load test that asserts memory per worker stays flat.

If a service reads the request, the session, or the auth guard, it is not a singleton. Full stop.

Is it worth it?

MetricFPMOctane (Swoole)
p50 latency48 ms11 ms
p99 latency210 ms64 ms
Servers62

Yes — but only once the team treats boot-time state as a shared resource.

Written by

Tubagus

Full Stack Developer

Share this note

Next note

One schema, two runtimes: API contracts with Zod→