Laravel Octane: the performance that comes with a persistent process
How Laravel Octane eliminates per-request bootstrap overhead — and the trade-offs that come with it.
Laravel Octane reached a stable release earlier this year. I had been following the project for a long time, and last month I finally had the chance to try it on a real application. It met my expectations — and then some. But it also raised the question: what’s the cost? Before answering that, it’s worth understanding why Octane makes such a difference in the first place.
PHP’s default model: starting from scratch on every request
PHP’s traditional execution model works like this: an HTTP request arrives, a PHP process starts, the entire framework bootstraps, the request is handled, and the process terminates. The next request repeats the same cycle.
This model is clean in many ways. State doesn’t bleed from one request to the next, memory issues resolve themselves, and a bug that crashes one request doesn’t affect the next.
But it has a cost: framework bootstrapping runs on every single request. Registering service providers, reading configuration files, defining bindings — all of this happens repeatedly. In a mid-sized Laravel application, that’s roughly 20–50 ms of overhead per request.
Octane’s model: a warmed-up process
Laravel Octane is built on top of Swoole or RoadRunner. These tools run PHP as a persistent, long-running process. The application bootstraps once and then continues serving requests from that already-bootstrapped state.
The result: the first request is no longer more expensive than subsequent ones. The application is already warm and ready.
The setup is relatively straightforward:
composer require laravel/octane
php artisan octane:install
php artisan octane:start --server=swoole --port=8000
A rough comparison of response times for a simple route looks something like this:
| Scenario | PHP-FPM | Octane (Swoole) |
|---|---|---|
| Simple route | ~15 ms | ~2 ms |
| Route with a database query | ~35 ms | ~18 ms |
| Complex route (many services) | ~80 ms | ~25 ms |
The exact numbers vary by application, but the ratio is consistent.
Trade-off 1: State leakage
This is the most critical issue. In PHP’s traditional model, state problems tend to resolve themselves — the next request starts in a fresh process. With Octane, the same process is reused across many requests, so static properties, singletons, and global variables can bleed between requests.
<?php
// THIS IS DANGEROUS — static property persists between requests
class RequestLogger
{
private static array $logs = [];
public static function add(string $message): void
{
self::$logs[] = $message; // Keeps accumulating on every request!
}
}
Octane provides listeners alongside the octane:start command — hooks that run before and after each request. But you do need to audit your existing code for this model.
Laravel’s own components are Octane-compatible. Problems typically surface in singletons you’ve written yourself or in third-party packages that weren’t built with persistent processes in mind.
Trade-off 2: Swoole requirements
Swoole is installed as a C extension to PHP. It doesn’t ship with a standard PHP installation and has to be installed separately on the server. This narrows your hosting options.
RoadRunner is the alternative: written in Go, it runs standard PHP as a long-running process. It’s not as fast as Swoole, but the setup involves considerably less friction.
Trade-off 3: Development environment
In development mode, hot reload works: when you save a file, Octane restarts the application process. It provides an environment close to production, but it doesn’t behave exactly the same as traditional PHP-FPM.
You’ll also want to verify that your debug tools and profilers work properly with Octane.
When it’s worth it
Octane isn’t the right choice for every project. I wouldn’t recommend migrating a low-traffic content site or an admin panel — the gains there are invisible, and the risk is unnecessary.
For high-traffic APIs, real-time features, or applications where response time is actively measured and monitored, it’s a meaningful improvement. In particular, where you need WebSocket support or concurrent task execution, the additional capabilities Swoole brings are valuable in their own right.
If you’re migrating an existing project, start by auditing your state management. Review static property usage, global state, and singletons. That cleanup often improves the project independently of Octane.
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.