Octane

Laravel Octane and the Long-Lived Worker Model

Under PHP-FPM, every request boots the framework again, and OPcache only makes that cheaper. Octane 4,043 2.20.0 boots the application once in a long-running worker on FrankenPHP 912,500 , Swoole 18,923 , Open Swoole or RoadRunner, and serves request after request from the same memory. That shared memory is both why Octane is fast and where its bugs come from:

A route that counts its own requestsPHP
Route::get('/hits', function () {
    static $hits = 0;               // lives as long as the PHP process does
    return ['hits' => ++$hits, 'pid' => getmypid()];
});
Output
--- php artisan serve
{"hits":1,"pid":246203}
{"hits":1,"pid":246203}
{"hits":1,"pid":246203}
--- octane
{"hits":1,"pid":248279}
{"hits":2,"pid":248279}
{"hits":3,"pid":248279}

The second run used octane:start --server=frankenphp --workers=1 on FrankenPHP 1.12.7 (PHP 8.5.10). Under artisan serve, the same process reset its state after every response. Under Octane, the state carried over. Singletons that keep $request or the user, static caches and growing arrays all leak from one request into the next. Inject Request into methods, not constructors, and let --max-requests recycle workers. (octane:install hit GitHub 29 's API rate limit here, so the FrankenPHP binary came from its release page.)