Home PHP Laravel Octane: Supercharge Your App with High-Performance Serving
Advanced 4 min · July 13, 2026

Laravel Octane: Supercharge Your App with High-Performance Serving

Master Laravel Octane to boost performance using Swoole or RoadRunner.

N
Naren Founder & Principal Engineer

20+ years shipping production PHP systems at scale. Everything here is grounded in real deployments.

Follow
Production
production tested
July 13, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 20-25 min read
  • Basic knowledge of Laravel framework
  • Familiarity with Composer and PHP CLI
  • Access to a server with root privileges (for Swoole installation)
  • Understanding of HTTP and request lifecycle
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Laravel Octane supercharges your application by keeping it in memory across requests, eliminating bootstrap overhead.
  • It supports Swoole and RoadRunner as high-performance application servers.
  • Octane can increase throughput by 10-30x compared to traditional PHP-FPM.
  • Requires careful handling of static properties, singletons, and request-specific state.
  • Production deployment needs proper configuration, monitoring, and graceful shutdown.
✦ Definition~90s read
What is Laravel Octane?

Laravel Octane is a package that supercharges your Laravel application by using high-performance application servers like Swoole or RoadRunner to keep the framework booted in memory across requests, dramatically increasing throughput.

Imagine a restaurant kitchen.
Plain-English First

Imagine a restaurant kitchen. Traditional PHP-FPM is like a chef who prepares every dish from scratch, including washing the pans and chopping vegetables, for each customer. Laravel Octane is like a chef who keeps the kitchen prepped and ready, so when an order comes in, they just cook the dish quickly. This makes serving many customers much faster.

Laravel Octane is a first-party package that dramatically boosts your Laravel application's performance by using high-powered application servers like Swoole and RoadRunner. Instead of booting the framework from scratch for every request (as with PHP-FPM), Octane boots the application once, keeps it in memory, and reuses it across all subsequent requests. This eliminates the overhead of framework bootstrap, configuration loading, and service container resolution, resulting in massive performance gains—often 10 to 30 times more requests per second.

But with great power comes great responsibility. Octane's long-lived application state introduces new challenges: you must be careful with static properties, singletons, and any mutable global state. A memory leak or stale data can affect subsequent requests. This tutorial will guide you through setting up Octane, writing Octane-safe code, deploying to production, and debugging common issues. You'll learn how to harness Octane's power without falling into its traps.

Whether you're building a high-traffic API, a real-time dashboard, or a SaaS platform, Octane can help you serve more users with fewer servers. Let's dive in and supercharge your Laravel app.

Installation and Configuration

To get started with Laravel Octane, you need to install the package via Composer. Octane requires either Swoole or RoadRunner as the underlying server. For this tutorial, we'll use Swoole, which is a PHP extension that provides an event-driven, asynchronous, concurrent networking framework.

``bash composer require laravel/octane ``

Next, install Swoole via PECL or using the official Docker image. For local development, you can use the provided Docker setup. After installation, publish the Octane configuration:

``bash php artisan octane:install ``

This will create a config/octane.php file where you can configure the server, worker count, max requests per worker, and more. A typical configuration might look like:

``php return [ 'server' => env('OCTANE_SERVER', 'swoole'), 'workers' => env('OCTANE_WORKERS', 4), 'max_requests' => 500, 'swoole' => [ 'options' => [ 'log_file' => storage_path('logs/swoole.log'), 'log_level' => 4, ], ], ]; ``

``bash php artisan octane:start ``

By default, Octane listens on port 8000. You can test it by visiting http://localhost:8000. For production, you'll want to use a process monitor like Supervisor to keep Octane running.

config/octane.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

return [
    'server' => env('OCTANE_SERVER', 'swoole'),
    'workers' => env('OCTANE_WORKERS', 4),
    'max_requests' => 500,
    'swoole' => [
        'options' => [
            'log_file' => storage_path('logs/swoole.log'),
            'log_level' => 4,
        ],
    ],
];
💡Choosing the Right Server
📊 Production Insight
Set max_requests to a value like 500 to prevent memory leaks from accumulating. This forces workers to restart after serving that many requests.
🎯 Key Takeaway
Install Octane via Composer, choose Swoole or RoadRunner, and configure worker count and max requests per worker.

Writing Octane-Safe Code

Octane's long-lived application state means you must be careful with global or static state. Any mutable static property or singleton that holds request-specific data will persist across requests, causing data leakage and bugs.

Avoid static properties that change per request. For example:

```php class UserService { public static $user;

public function setUser($user) { self::$user = $user; } } ```

This is dangerous because $user will be overwritten by concurrent requests. Instead, use request-scoped dependencies or pass data via method parameters.

Use scoped bindings in the service container. Instead of registering a singleton, use a closure that returns a new instance per request:

``php $this->app->bind(UserService::class, function ($app) { return new UserService($app['request']->user()); }); ``

Leverage Octane's flush strategies for caches that should be cleared per request. Octane provides a flush method on the Octane facade that you can call in middleware to reset state:

```php use Laravel\Octane\Facades\Octane;

public function handle($request, $next) { $response = $next($request); Octane::flush(); return $response; } ```

This will reset any registered flushable instances. You can also use the Octane::flush() method in your code after sending a response.

Be cautious with facades that cache data. For example, Config::get() caches configuration values, but that's fine because config is immutable. However, facades like Cache that store data in memory may need careful handling.

app/Http/Middleware/OctaneFlush.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

namespace App\Http\Middleware;

use Closure;
use Laravel\Octane\Facades\Octane;

class OctaneFlush
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        Octane::flush();
        return $response;
    }
}
⚠ Singleton Trap
📊 Production Insight
In production, use a middleware that calls Octane::flush() after each request to ensure clean state. But be mindful of performance; only flush what's necessary.
🎯 Key Takeaway
Avoid static state, use scoped bindings, and leverage Octane's flush mechanism to reset per-request state.

Handling Database Connections and Queues

Octane works with Laravel's database and queue systems, but you need to be aware of connection pooling and transaction management.

Database connections are reused across requests. Octane automatically manages connection pooling for MySQL and PostgreSQL. However, if you use transactions, ensure they are committed or rolled back before the request ends. A dangling transaction can block subsequent queries.

Queue workers can be run alongside Octane. However, Octane's workers are not queue workers. You should run separate queue workers using php artisan queue:work. Octane can also dispatch jobs synchronously, but for heavy jobs, use a dedicated queue.

Redis connections are also pooled. Be careful with Redis transactions and pub/sub. Avoid blocking operations like BLPOP in request handlers; use async alternatives.

Example of safe transaction handling:

``php DB::beginTransaction(); try { // ... DB::commit(); } catch (\Exception $e) { DB::rollBack(); throw $e; } ``

Always ensure transactions are closed. In Octane, if an exception occurs and the transaction is not rolled back, the connection will be returned to the pool with an open transaction, causing issues for the next request.

app/Http/Controllers/OrderController.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    public function store(Request $request)
    {
        DB::beginTransaction();
        try {
            $order = Order::create($request->validated());
            // ...
            DB::commit();
            return response()->json($order, 201);
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }
}
🔥Connection Pool Tuning
📊 Production Insight
Set 'options' => [PDO::ATTR_EMULATE_PREPARES => true] in your database config to reduce memory usage in Octane.
🎯 Key Takeaway
Always close transactions, use connection pooling wisely, and run queue workers separately.

Deploying Octane to Production

Deploying Octane requires a process manager like Supervisor to keep the server running. Here's a sample Supervisor configuration:

``ini [program:laravel-octane] process_name=%(program_name)s_%(process_num)02d command=php /path/to/artisan octane:start --server=swoole --host=0.0.0.0 --port=8000 autostart=true autorestart=true user=forge numprocs=1 redirect_stderr=true stdout_logfile=/path/to/storage/logs/octane.log stopwaitsecs=60 ``

Graceful shutdown is important. Octane listens for signals like SIGTERM and will finish current requests before shutting down. Ensure your Supervisor config sends the correct signal.

Health checks should verify that Octane is responding. You can create a simple route:

``php Route::get('/health', function () { return response()->json(['status' => 'ok']); }); ``

Then configure your load balancer to hit this endpoint.

Environment variables like APP_ENV and APP_DEBUG should be set appropriately. In production, set APP_DEBUG=false and OCTANE_WORKERS to the number of CPU cores.

Logging is crucial. Octane logs to the file specified in config. Monitor these logs for errors and warnings.

/etc/supervisor/conf.d/octane.confPHP
1
2
3
4
5
6
7
8
9
10
11
[program:laravel-octane]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
autostart=true
autorestart=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/octane.log
stopwaitsecs=60
💡Load Balancer Sticky Sessions
📊 Production Insight
Set OCTANE_MAX_REQUESTS to a value like 500 to automatically recycle workers and prevent memory leaks.
🎯 Key Takeaway
Use Supervisor to manage Octane, configure graceful shutdown, and implement health checks.

Monitoring and Debugging Octane

Monitoring Octane in production is essential. Key metrics to watch:

  • Memory usage: Use php artisan octane:status to see memory per worker. Set up alerts if memory exceeds a threshold.
  • Request throughput: Use tools like Laravel Telescope or New Relic.
  • Worker restarts: If workers restart frequently, check for exceptions or memory limits.

Debugging tips:

  • Use php artisan octane:reload to gracefully restart workers without downtime.
  • Enable Swoole's trace log level for detailed debugging.
  • Use dd() or dump() carefully; they may output to the console of the worker, not the HTTP response. Use logger() instead.
  • For profiling, use Blackfire or Xdebug with caution. Xdebug can slow down Octane significantly.

Common issues:

  • Stale data: If you see data from previous requests, check for static caches or singletons.
  • Connection timeouts: Increase max_execution_time in Swoole options.
  • Serialization errors: When using queues, ensure job payloads are serializable. Avoid closures that capture request objects.
app/Console/Commands/OctaneStatus.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Laravel\Octane\Facades\Octane;

class OctaneStatus extends Command
{
    protected $signature = 'octane:custom-status';

    public function handle()
    {
        $status = Octane::status();
        $this->info(json_encode($status, JSON_PRETTY_PRINT));
    }
}
⚠ Avoid dd() in Octane
📊 Production Insight
Integrate with a centralized logging system like Papertrail or ELK to aggregate logs from all workers.
🎯 Key Takeaway
Monitor memory and throughput, use octane:reload for graceful restarts, and avoid debugging functions that kill workers.

Advanced: Coroutines and Async I/O

Swoole provides coroutines that allow concurrent I/O operations without blocking the worker. This can further boost performance for I/O-bound tasks like multiple database queries or HTTP calls.

Using coroutines in Octane:

```php use Swoole\Coroutine; use Illuminate\Support\Facades\Http;

$responses = Coroutine::wait([ Coroutine::create(function () { return Http::get('https://api.example.com/users'); }), Coroutine::create(function () { return Http::get('https://api.example.com/posts'); }), ]); ```

However, be cautious: Laravel's facades and Eloquent are not coroutine-safe. You must ensure that any shared state is not mutated concurrently. Use go() and defer() carefully.

Octane's task workers can be used for CPU-intensive tasks. Configure them in config/octane.php:

``php 'swoole' => [ 'options' => [ 'task_worker_num' => 4, ], ], ``

``php $result = Octane::task(function () { // CPU-intensive work return heavyComputation(); }); ``

Task workers run in separate processes, so they don't block request handling.

app/Http/Controllers/AsyncController.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

namespace App\Http\Controllers;

use Swoole\Coroutine;
use Illuminate\Support\Facades\Http;

class AsyncController extends Controller
{
    public function index()
    {
        $responses = Coroutine::wait([
            Coroutine::create(function () {
                return Http::get('https://api.example.com/users');
            }),
            Coroutine::create(function () {
                return Http::get('https://api.example.com/posts');
            }),
        ]);

        return response()->json([
            'users' => $responses[0]->json(),
            'posts' => $responses[1]->json(),
        ]);
    }
}
🔥Coroutine Safety
📊 Production Insight
Start with task workers before coroutines; they are simpler and safer. Only use coroutines if you fully understand the implications.
🎯 Key Takeaway
Coroutines can parallelize I/O, but require careful coding to avoid race conditions. Task workers handle CPU-heavy work.
● Production incidentPOST-MORTEMseverity: high

The Case of the Leaking Singleton: A Production Outage

Symptom
After deploying Octane, memory usage grew steadily over hours, eventually causing the server to run out of memory and crash. Requests became slower and eventually timed out.
Assumption
The developer assumed that since the application worked fine with PHP-FPM, it would work the same with Octane. They thought Octane was just a drop-in replacement.
Root cause
A service registered as a singleton in the container held a reference to a request-specific object (like the authenticated user). Because the singleton persisted across requests, the object was never garbage-collected, leading to memory leak.
Fix
Changed the binding from singleton to scoped (using bind with a closure that returns a new instance per request) or ensured the singleton did not hold request-specific data. Also added memory limit monitoring and alerts.
Key lesson
  • Never store request-specific data in singletons or static properties.
  • Use scoped bindings for services that depend on request state.
  • Monitor memory usage closely when deploying Octane.
  • Test under load with realistic traffic patterns before production.
  • Implement graceful shutdown and health checks to detect leaks early.
Production debug guideSymptom to Action4 entries
Symptom · 01
Memory usage grows over time
Fix
Check for singletons holding request data, use memory profiling tools like Blackfire or Xdebug, review static properties.
Symptom · 02
Stale data appears across requests
Fix
Look for cached query results or static caches that are not cleared per request. Use Octane's flush strategies.
Symptom · 03
Application crashes with 'Maximum execution time exceeded'
Fix
Ensure long-running tasks are offloaded to queues. Check for blocking I/O operations that should be async.
Symptom · 04
Errors about 'Serialization of closures'
Fix
Avoid serializing closures that capture request-specific state. Use queueable jobs instead.
★ Quick Debug Cheat SheetCommon Octane issues and immediate actions
Memory leak
Immediate action
Restart Octane server
Commands
php artisan octane:reload
php artisan octane:status
Fix now
Identify and fix singleton/static state
Stale data+
Immediate action
Clear cache and restart
Commands
php artisan optimize:clear
php artisan octane:reload
Fix now
Use request-scoped bindings
High CPU usage+
Immediate action
Check for infinite loops
Commands
top -c
php artisan octane:status
Fix now
Optimize heavy queries or offload to queue
Connection pool exhaustion+
Immediate action
Increase pool size
Commands
php artisan config:cache
php artisan octane:reload
Fix now
Tune database and Redis connection pools
FeaturePHP-FPMLaravel Octane (Swoole)
Bootstrap per requestYesNo (once)
Memory footprintLow per requestHigher but shared
ThroughputBaseline10-30x higher
ConcurrencyProcess-basedCoroutine-based
Static state safetySafe (per request)Requires caution
Setup complexitySimpleModerate
DebuggingEasierMore complex
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
configoctane.phpreturn [Installation and Configuration
appHttpMiddlewareOctaneFlush.phpnamespace App\Http\Middleware;Writing Octane-Safe Code
appHttpControllersOrderController.phpnamespace App\Http\Controllers;Handling Database Connections and Queues
etcsupervisorconf.doctane.conf[program:laravel-octane]Deploying Octane to Production
appConsoleCommandsOctaneStatus.phpnamespace App\Console\Commands;Monitoring and Debugging Octane
appHttpControllersAsyncController.phpnamespace App\Http\Controllers;Advanced

Key takeaways

1
Laravel Octane boosts performance by keeping the application in memory across requests, but requires careful handling of static state and singletons.
2
Use scoped bindings, avoid static properties, and leverage Octane's flush mechanism to prevent data leakage.
3
Monitor memory usage and worker restarts, and use process managers like Supervisor for production deployment.
4
Coroutines and task workers can further optimize I/O and CPU-bound tasks, but introduce complexity.

Common mistakes to avoid

3 patterns
×

Using static properties to store request data

×

Not closing database transactions

×

Using dd() or dump() in request handlers

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
What is Laravel Octane and how does it improve performance?
Q02SENIOR
What are the main pitfalls when using Octane with existing Laravel code?
Q03SENIOR
How do you handle database transactions in Octane to avoid connection po...
Q01 of 03SENIOR

What is Laravel Octane and how does it improve performance?

ANSWER
Laravel Octane is a package that uses high-performance application servers like Swoole or RoadRunner to boot the Laravel application once and keep it in memory across requests, eliminating bootstrap overhead. This can increase throughput by 10-30x.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I use Octane with shared hosting?
02
Does Octane work with Laravel Horizon?
03
How do I handle file uploads in Octane?
04
What is the difference between Swoole and RoadRunner?
05
Can I use Octane with Laravel Vapor?
N
Naren Founder & Principal Engineer

20+ years shipping production PHP systems at scale. Everything here is grounded in real deployments.

Follow
Verified
production tested
July 13, 2026
last updated
2,073
articles · all by Naren
🔥

That's Laravel. Mark it forged?

4 min read · try the examples if you haven't

Previous
Laravel Pulse and Pennant: Monitoring and Feature Flags
19 / 24 · Laravel
Next
Laravel Horizon and Telescope: Queue Monitoring and Debugging