
Performance
Laravel Octane vs PHP-FPM: Supercharging Your App's Performance
Benchmark Laravel Octane (Swoole/RoadRunner) against traditional PHP-FPM. See the throughput gains, real-world scenarios, and pitfalls to watch for before switching.
Every request to a traditional Laravel app pays the same tax: boot the framework, load the container, resolve every service provider, handle the request, then throw it all away and do it again next time. Laravel Octane exists to eliminate that tax , and the performance difference is large enough that it's worth understanding exactly how it works before deciding whether to switch.
This guide compares Octane against classic PHP-FPM, shows realistic performance expectations, and covers the pitfalls that catch teams off guard when they adopt it.
Table of Contents#
- The Core Difference
- 1. How Octane Works
- 2. Performance Comparison
- 3. Real-World Scenarios
- 4. Risks & Best Practices
- Octane Migration Checklist
- FAQ
- Resources
The Core Difference#
PHP-FPM (traditional model): every incoming request spins up a fresh PHP process (or reuses a worker that still re-bootstraps the app), builds the entire Laravel service container from scratch, handles the request, then discards everything. This is simple, safe, and stateless by default , which is exactly why it's been the default for so long.
Octane: boots the Laravel application once into a long-running worker process (via Swoole or RoadRunner), then feeds it requests at high speed without rebuilding the container each time. The app stays resident in memory between requests.
1. How Octane Works#
- On startup, Octane boots your full Laravel application once per worker and keeps it in memory.
- Incoming requests are handed to an already-booted worker instead of triggering a fresh bootstrap.
- Workers are managed by a high-performance application server , Swoole (a PHP extension) or RoadRunner (a Go-based server) , both of which handle the event loop and worker pool.
- Because the app persists between requests, anything you'd normally expect to reset per-request (static properties, singleton state, service container bindings) can leak between requests if you're not careful. This is the single biggest mental shift Octane requires.
composer require laravel/octane
php artisan octane:install --server=swoole
# or
php artisan octane:install --server=roadrunner
php artisan octane:start --workers=4 --task-workers=6
2. Performance Comparison#
The throughput difference comes almost entirely from skipping the bootstrap cost on every request. For a typical Laravel app, that bootstrap , autoloading, service provider registration, config/route caching lookups , is often a meaningful fraction of total request time, especially for lightweight endpoints.
| Metric | PHP-FPM | Octane (Swoole/RoadRunner) |
|---|---|---|
| App bootstrap | Every request | Once per worker |
| Typical TTFB (simple endpoint) | ~20–50ms | ~3–10ms |
| Relative throughput (requests/sec) | Baseline | Meaningfully higher , often 2–3× on I/O-light endpoints |
| Memory per worker | Lower, released after each request | Higher , app state persists |
| Concurrency model | Process-per-request | Persistent event-loop workers |
The exact multiplier depends heavily on your specific app , how heavy your service provider registration is, how many packages you're loading, and how much of your request time is spent in the framework bootstrap vs. actual business logic (database queries, external API calls). Apps with lean bootstraps and I/O-heavy endpoints see the biggest relative gains; apps that are already dominated by slow database queries see less, because Octane doesn't make your queries faster.
3. Real-World Scenarios#
Where Octane shines:
- High-traffic, read-heavy APIs serving mostly cached or lightweight responses
- Endpoints with a lot of bootstrap overhead relative to actual work (many service providers, heavy config)
- Applications already hitting PHP-FPM worker limits under load
Where it's a smaller win , or a real risk:
- Legacy applications that rely on static properties or singletons holding per-request state , these can leak data between requests once the app stops resetting on every call, which is a serious correctness bug, not just a performance quirk
- Apps where request time is dominated by slow database queries or external API calls , Octane speeds up the framework layer, not your queries
- Packages that assume a fresh application instance per request and don't clean up properly
4. Risks & Best Practices#
-
Audit static state before switching. Any static property, singleton, or
app()->instance()binding that holds request-specific data needs to be reset between requests, or it will leak between users. This is the most common and most dangerous Octane migration bug. -
Check package compatibility. Not every package is "Octane-safe" , some assume a clean boot every request. Laravel maintains guidance on this; test thoroughly with realistic traffic before trusting a package in production under Octane.
-
Expect higher baseline memory usage. Because the app stays resident, each worker holds more memory than a stateless PHP-FPM process. Size your worker count and server memory accordingly , more isn't always better if it starves the server.
-
Test under real concurrent load, not just single requests. Bugs from shared state usually only show up when multiple requests are actually running through the same worker concurrently , a single manual test won't catch them.
-
Don't reach for Octane by default. If your app isn't under meaningful load and PHP-FPM is meeting your latency needs, the migration effort and added operational complexity may not be worth it yet.
Octane Migration Checklist#
- Chosen a server (Swoole or RoadRunner) based on your infra and team familiarity
- Audited the codebase for static properties, singletons, and container bindings holding per-request state
- Verified all critical third-party packages are confirmed Octane-safe
- Load-tested with realistic concurrent traffic, not just sequential requests
- Sized worker count against available server memory
- Set up monitoring for memory growth over time (a sign of a state leak)
- Confirmed request-scoped services (like the current authenticated user) reset correctly between requests
- Rollback plan in place in case a production issue surfaces post-migration
FAQ#
Is Laravel Octane a replacement for PHP-FPM entirely? Not necessarily , it's a different deployment model with real trade-offs, not a strict upgrade. It's best suited to high-traffic or latency-sensitive apps. Smaller apps or ones with plenty of headroom under PHP-FPM may not need it.
Does Octane work with Laravel's queue system? Yes, and Octane even provides its own task worker pool for offloading work, but the same static-state caution applies , job classes need to be written to not leak state between executions just like controllers do.
How risky is migrating an existing large app to Octane? It depends heavily on how much the codebase relies on the "fresh boot every request" assumption. A well-structured Laravel app following standard dependency injection patterns usually migrates cleanly; an older app with heavy use of static state or global singletons will need real auditing work first. Budget time for testing, not just installation.