The Short Version
For a Laravel Octane API that must handle thousands of requests per second, use Swoole when you need the lowest latency, tune the worker and task settings to match your CPU cores, enable opcode caching, keep the container stateless, and profile with Laravel Telescope or the built‑in Octane metrics.
What Octane adds to a Laravel API
Octane boots the Laravel framework once and reuses that instance across many HTTP requests. This removes the cost of loading service providers, compiling Blade files and rebuilding the service container on every call. The result is a dramatic reduction in request‑time overhead, which is most noticeable on endpoints that perform only a small amount of business logic.
Typical bottlenecks in high‑traffic APIs
| Symptom | Common cause | Quick fix |
|---|---|---|
| CPU spikes at 70 %+ | Too many Octane workers per core | Set workers to cpu * 2 |
| Memory growth per request | Stateful singletons in the container | Move mutable data to the request scope |
| Slow database queries | Unoptimised Eloquent queries | Use eager loading or raw queries where appropriate |
| Latency spikes under load | Blocking I/O in middleware | Replace with async‑compatible packages or queue the work |
Choosing the right server driver
Octane supports two production‑grade servers: Swoole and RoadRunner. Both run PHP processes outside the traditional FPM model, but they differ in how they handle workers, tasks and hot‑reloading.
Swoole
- Event‑driven, low‑latency networking
- Native coroutine support – useful for async HTTP clients
- Requires the
swoolePECL extension (compatible with PHP 8.2) - Best for APIs that need sub‑millisecond response times
RoadRunner
- Runs as a separate binary written in Go
- Manages PHP worker pools without a PHP extension
- Stable across PHP versions, easier to install on shared hosts
- Suitable when you prefer a simpler deployment pipeline
Essential Octane configuration
The following snippet shows a minimal config/octane.php for Laravel 10 with Swoole. Adjust the values to match the number of CPU cores on your server.
// config/octane.php
return [
'server' => env('OCTANE_SERVER', 'swoole'),
// Number of workers – start with cpu * 2
'workers' => env('OCTANE_WORKERS', 8),
// Maximum requests a worker handles before recycling
'max_requests' => env('OCTANE_MAX_REQUESTS', 500),
// Enable opcode caching (OPcache must be enabled in php.ini)
'opcache' => true,
// Keep the container stateless – avoid bindings that store request data
'force_https' => false,
];
For RoadRunner the server key changes to roadrunner, and you can add a processes section to control the worker pool size.
Profiling with Octane metrics
Octane ships with a built‑in metrics endpoint. Start the server with the --metrics flag and query /octane/metrics to see real‑time values such as requests_per_second, memory_usage and worker_idle_time. Pair this with Laravel Telescope to drill down into individual request traces.
Stateless design patterns for Octane
Because the same Laravel instance serves many requests, any object that retains state between calls can cause memory leaks or data bleed. Follow these rules:
- Never store user‑specific data in a singleton service.
- Use request‑scoped bindings for services that need per‑request configuration.
- Prefer value objects over mutable class properties.
Keep the container clean
Register services that depend on the current request inside a closure, e.g. app()->bind(UserContext::class, fn () => new UserContext(request())). This ensures each request gets its own instance and prevents cross‑talk.


