DEV Community

Cover image for Running Laravel Octane on Deploynix: FrankenPHP, RoadRunner & Swoole
Deploynix
Deploynix

Posted on • Originally published at deploynix.io

Running Laravel Octane on Deploynix: FrankenPHP, RoadRunner & Swoole

Laravel Octane fundamentally changes how your PHP application handles requests. Instead of booting the framework from scratch on every single request — loading configuration, registering service providers, resolving bindings — Octane boots the application once and keeps it in memory, serving subsequent requests from that warm state. The result is dramatically faster response times and significantly higher throughput.

Deploynix supports all three Octane drivers: FrankenPHP, RoadRunner, and Swoole. Each has its own strengths, trade-offs, and ideal use cases. In this guide, we will cover how to enable Octane on Deploynix, how to choose the right driver for your application, performance characteristics you can expect, and the gotchas you need to watch out for when moving from traditional PHP-FPM to an Octane-powered setup.

How Octane Changes the Game

To understand why Octane matters, you need to understand how traditional PHP-FPM works.

With PHP-FPM, every incoming request triggers a full bootstrap of your Laravel application. The framework reads configuration files, registers service providers, boots services, resolves route middleware, and then finally handles your request. After the response is sent, everything is destroyed. The next request starts from scratch.

This model is simple and safe. There is no shared state between requests, so memory leaks are impossible and every request gets a clean environment. But it is also wasteful. If your application takes 30-50 milliseconds just to boot, that overhead exists on every single request, regardless of how simple the actual work is.

Octane eliminates this overhead by booting the application once and keeping it resident in memory. The framework is fully initialized, service providers are registered, and the application is ready to handle requests without any bootstrap cost. A request that previously took 80 milliseconds might now take 15 milliseconds because 65 milliseconds of that was framework bootstrapping.

The difference is most dramatic for applications with many service providers, complex configurations, or heavy IoC container usage — which describes most real-world Laravel applications.

Choosing Your Driver

Deploynix supports all three Octane drivers. Here is how they compare.

FrankenPHP

FrankenPHP is the newest driver and the one that has generated the most excitement in the Laravel community. It is a modern PHP application server built on top of Caddy, written in Go. FrankenPHP supports early hints (HTTP 103), worker mode, and automatic HTTPS.

Strengths:

  • Simplest setup process — single binary, no PHP extensions required
  • Built-in HTTPS with automatic certificate management
  • HTTP/3 and early hints support out of the box
  • Active development with strong community momentum
  • Worker mode keeps your application in memory similar to how Swoole does, but without needing a PHP extension

Best for: New projects and teams that want the simplest possible Octane setup with modern HTTP features.

Considerations: As the newest driver, it has the smallest ecosystem of community knowledge and troubleshooting resources, though this is growing rapidly.

RoadRunner

RoadRunner is a high-performance PHP application server written in Go. It has been around longer than FrankenPHP and has a proven track record in production environments.

Strengths:

  • Mature and battle-tested in production
  • No PHP extensions required — uses standard PHP workers
  • Built-in support for queues, WebSockets, and gRPC
  • Extensive plugin ecosystem
  • Excellent documentation and community support

Best for: Production workloads where stability and proven performance are the priority. Particularly strong for applications that also need WebSocket or gRPC capabilities.

Considerations: Configuration is more involved than FrankenPHP. The .rr.yaml configuration file has many options that can be overwhelming at first.

Swoole

Swoole is a PHP extension that brings asynchronous, event-driven programming to PHP. It has been the Octane driver of choice for teams that need maximum performance and are comfortable with the trade-offs.

Strengths:

  • Highest raw performance of the three drivers
  • True asynchronous I/O — database queries, HTTP requests, and file operations can run concurrently
  • Coroutine support for concurrent programming
  • The most mature Octane driver with the longest track record

Best for: Applications where every millisecond counts, teams comfortable with PHP extensions, and use cases that benefit from asynchronous I/O (high-concurrency APIs, real-time applications).

Considerations: Requires the Swoole PHP extension, which adds complexity to your server configuration. Some PHP libraries are not Swoole-compatible. The async programming model can introduce subtle bugs if you are not careful.

Enabling Octane on Deploynix

Step 1: Install Octane in Your Application

First, add Octane to your Laravel application:

composer require laravel/octane
Enter fullscreen mode Exit fullscreen mode

Then publish the Octane configuration:

php artisan octane:install
Enter fullscreen mode Exit fullscreen mode

During installation, you will be asked to choose a driver. Select the one you want to use. This creates the config/octane.php configuration file.

Step 2: Configure Your Deploynix Site

In your Deploynix dashboard, navigate to your site's settings. Look for the Octane configuration section.

Enable Octane and select your driver (FrankenPHP, RoadRunner, or Swoole).

When you enable Octane, Deploynix reconfigures Nginx to proxy requests to the Octane server instead of PHP-FPM. The Octane process is managed by Supervisor, ensuring it restarts automatically if it crashes or if the server reboots.

Deploynix handles the Octane setup automatically by running composer require laravel/octane and php artisan octane:install with your chosen driver. Laravel's Octane installer takes care of downloading the appropriate driver binary or configuring the required extension.

For FrankenPHP, no additional PHP extensions are needed — the driver is installed via Composer.

For RoadRunner, the binary is downloaded and a .rr.yaml configuration is generated during installation.

For Swoole, the Swoole PHP extension must be available on the server. If it is not already installed, you can install it via SSH before enabling Octane.

Step 3: Configure Workers

The number of Octane workers determines how many concurrent requests your application can handle. A good starting point is to match the number of CPU cores on your server.

For a 2 vCPU server, start with 2 workers. For a 4 vCPU server, start with 4 workers. You can adjust this based on monitoring data once your application is running.

Set the OCTANE_WORKERS environment variable or configure it in config/octane.php:

'workers' => env('OCTANE_WORKERS', 4),
Enter fullscreen mode Exit fullscreen mode

Step 4: Deploy

Trigger a deployment. Deploynix will install your Octane driver, configure Nginx, start the Octane server process, and begin routing traffic through it.

Performance Expectations

The performance improvement you see from Octane depends heavily on your application's characteristics.

Request-heavy applications (APIs serving many small, fast requests) see the most dramatic improvement because the framework bootstrap overhead is a larger proportion of total request time. A simple API endpoint that took 40 milliseconds with FPM might take 5-10 milliseconds with Octane.

Database-heavy applications see a smaller relative improvement because the database query time dominates. If your endpoint takes 200 milliseconds and 180 milliseconds of that is database queries, Octane might bring the total to 160 milliseconds — a noticeable improvement, but not the 4-8x speedup you see with lighter workloads.

Throughput (requests per second) typically improves by 2-4x for most applications. Since each request is processed faster and workers are reused without bootstrap overhead, the same server can handle significantly more traffic.

A Rough Benchmark Guide

These numbers are illustrative, not guaranteed. Your results will vary based on your application.

Metric PHP-FPM Octane (FrankenPHP) Octane (RoadRunner) Octane (Swoole)
Simple API response 35-50ms 5-12ms 5-10ms 3-8ms
Database query endpoint 80-120ms 50-80ms 45-75ms 40-70ms
Requests/sec (2 vCPU) 200-400 800-1500 900-1600 1000-2000
Memory per worker 30-50MB 40-60MB 35-55MB 45-65MB

The Gotchas: What Breaks When You Switch

Octane's persistent application state is both its greatest strength and its most dangerous trap. Code patterns that work perfectly fine under PHP-FPM can cause subtle, hard-to-debug issues under Octane.

Static Properties and Singletons

Under PHP-FPM, static properties reset on every request. Under Octane, they persist across requests. If your code accumulates data in a static property, that data leaks between requests.

// DANGEROUS under Octane
class RequestLogger
{
    public static array $logs = [];

    public static function log(string $message): void
    {
        static::$logs[] = $message; // Grows forever!
    }
}
Enter fullscreen mode Exit fullscreen mode

Fix: Use Octane's flush callbacks to reset state between requests, or avoid static state altogether. Laravel's built-in services are already Octane-compatible, but third-party packages and custom code need auditing.

Container Resolved Singletons

If you bind a service as a singleton in the container and that service holds request-specific state (like the authenticated user), that state persists into the next request.

Fix: Use $app->scoped() instead of $app->singleton() for services that hold request-specific data. Scoped bindings are resolved once per request and flushed automatically.

Global Helpers Holding State

The request(), auth(), and session() helpers work correctly under Octane because Laravel resets them between requests. But if you cache the result of these helpers in a property during boot, that cached value persists.

// DANGEROUS under Octane
class SomeService
{
    private User $user;

    public function __construct()
    {
        $this->user = auth()->user(); // Cached forever!
    }
}
Enter fullscreen mode Exit fullscreen mode

Fix: Resolve request-specific data at the time of use, not at construction time.

File Handles and Database Connections

Long-lived workers can exhaust file handles or database connections over time. Octane manages this by recycling workers after a configurable number of requests.

Set the --max-requests option to periodically restart workers. Deploynix defaults to 500 max requests, which you can adjust in the Octane settings (range: 100–10,000):

php artisan octane:start --max-requests=500
Enter fullscreen mode Exit fullscreen mode

This tells Octane to gracefully restart a worker after it has handled 500 requests, preventing memory leaks and stale connections from accumulating.

Third-Party Packages

Not all packages are Octane-compatible. Before enabling Octane, check the compatibility of your critical dependencies. The Laravel documentation maintains a list of known incompatibilities. Common issues include packages that use static state, persistent file locks, or singleton patterns that hold request-specific data.

Monitoring Your Octane Application

After switching to Octane, pay close attention to:

Memory usage per worker. Under FPM, memory is reclaimed after every request. Under Octane, workers persist, so memory leaks accumulate. Monitor worker memory usage through Deploynix's server monitoring dashboard and set up health alerts for high memory usage.

Response time consistency. Octane should deliver consistently fast responses. If you see occasional slow responses followed by fast ones, a worker might be encountering garbage collection pauses or memory pressure.

Error rates. Subtle Octane incompatibilities often manifest as intermittent errors rather than consistent failures. Monitor your error logs closely for the first few days after switching.

Falling Back to PHP-FPM

If you encounter issues with Octane that you cannot immediately resolve, switching back to PHP-FPM through the Deploynix dashboard is instant. Deploynix reconfigures Nginx to route requests back to PHP-FPM and stops the Octane process. Your application continues serving traffic without interruption.

This safety net means there is no risk in trying Octane. Enable it, monitor for a few days, and if everything looks good, keep it. If not, switch back with one click while you investigate.

Conclusion

Laravel Octane represents a significant leap in PHP application performance, and Deploynix makes enabling it straightforward regardless of which driver you choose. FrankenPHP offers simplicity and modern HTTP features, RoadRunner provides battle-tested stability, and Swoole delivers maximum raw performance.

The key to a successful Octane deployment is understanding that persistent application state changes the rules. Audit your code for static properties, singleton misuse, and request-specific data cached at construction time. Use Deploynix's monitoring tools to watch memory usage and response consistency.

Start with FrankenPHP if you want the easiest path, RoadRunner if you want proven stability, or Swoole if you want every last drop of performance. Deploynix supports all three, and switching between them is just a configuration change away.

Try Octane on your next deployment at deploynix.io.

Top comments (0)