Laravel Octane in 2026: Swoole, RoadRunner en Performance-optimalisatie

Complete handleiding voor Laravel Octane 2.19 met FrankenPHP, Swoole en RoadRunner. Serverselectie, memory leak preventie, concurrent taken en productie-deployment strategieën voor high-performance PHP-applicaties.

Laravel Octane Performance met FrankenPHP, Swoole en RoadRunner

Laravel Octane transformeert PHP-applicatie performance door het framework in geheugen geladen te houden tussen requests. Versie 2.19 (augustus 2026) ondersteunt drie productie-klare servers: FrankenPHP, Swoole en RoadRunner. Elke server voldoet aan verschillende operationele vereisten, en de verkeerde keuze kost ofwel performance ofwel stabiliteit.

Snelle Referentie voor Serverselectie

FrankenPHP: eenvoudigste setup, native HTTP/3, enkele binary. RoadRunner: beproefde Go-binary, geen PHP-extensies vereist. Swoole: maximale throughput met coroutine-concurrency, vereist PECL-extensiebeheer.

Hoe Octane Bootstrap-overhead Elimineert

Traditionele PHP-FPM start een nieuw proces per request. Laravel boot zijn service container, laadt configuratie, registreert providers en resolvet middleware bij elke HTTP-call. Octane keert dit model om: de applicatie boot één keer per worker, waarna dezelfde instantie duizenden requests sequentieel afhandelt.

De performance-winst komt van het elimineren van herhaald werk. Een typische Laravel 12-applicatie besteedt 15 tot 40ms aan bootstrapping voordat de business logic wordt uitgevoerd. Met Octane daalt deze kost naar nul na het eerste request. Benchmarks op identieke hardware tonen 2x tot 4x throughput-verbeteringen voor API-endpoints, waarbij het verschil groter wordt naarmate de applicatiecomplexiteit toeneemt.

config/octane.phpphp
return [
    'server' => env('OCTANE_SERVER', 'frankenphp'),
    
    // Workers handelen HTTP-requests af
    'workers' => env('OCTANE_WORKERS', 8),
    
    // Graceful restart van workers na N requests om memory bloat te voorkomen
    'max_requests' => env('OCTANE_MAX_REQUESTS', 500),
    
    // Task workers voor Swoole concurrent operaties
    'task_workers' => env('OCTANE_TASK_WORKERS', 6),
    
    // Maximale uitvoeringstijd per request in seconden
    'max_execution_time' => 30,
];

De max_requests instelling fungeert als veiligheidsklep. Zelfs goed geschreven code kan geheugen accumuleren over honderden requests. Dit op 500 zetten dwingt workers om te herstarten voordat geheugendruk problematisch wordt.

FrankenPHP: De Standaard voor Nieuwe Projecten in 2026

FrankenPHP wordt geleverd als enkele binary gebouwd op Caddy en PHP. Het handelt HTTPS-certificaten automatisch af via Let's Encrypt, ondersteunt HTTP/3 out-of-the-box en vereist geen PHP-extensies om te installeren. Laravel's installer en productie-voorbeelden gebruiken nu standaard FrankenPHP.

bash
# Installeer Octane met FrankenPHP
composer require laravel/octane
php artisan octane:install --server=frankenphp

# Start de server
php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000

Voor gecontaineriseerde deployments biedt FrankenPHP officiële Docker-images:

dockerfile
# Dockerfile
FROM dunglas/frankenphp

RUN install-php-extensions \
    pcntl \
    pdo_pgsql \
    redis

COPY . /app

ENTRYPOINT ["php", "artisan", "octane:frankenphp"]

De Docker Compose-configuratie voor development schakelt HTTPS en HTTP/3 in:

yaml
# compose.yaml
services:
  frankenphp:
    build:
      context: .
    entrypoint: php artisan octane:frankenphp --workers=1 --max-requests=1
    ports:
      - "443:443"
      - "443:443/udp"
    volumes:
      - .:/app

FrankenPHP handelt worker-restarts graceful af en integreert direct met Caddy's middleware-systeem voor geavanceerde routing-scenario's.

RoadRunner: Go-gebaseerde Stabiliteit Zonder Extensie-afhankelijkheden

RoadRunner compileert naar een Go-binary die PHP-worker processen beheert. Het communiceert met PHP via een binair protocol, waarbij worker-beheer en HTTP-handling in Go blijven terwijl applicatiecode in PHP wordt uitgevoerd. Deze architectuur biedt proces-isolatie: een crashende PHP-worker beïnvloedt noch de Go-parent noch sibling workers.

bash
# Installeer Octane met RoadRunner
composer require laravel/octane spiral/roadrunner-cli spiral/roadrunner-http

php artisan octane:install --server=roadrunner

# Download de RoadRunner binary
./vendor/bin/rr get-binary

# Start de server
php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000

RoadRunner-configuratie bevindt zich in .rr.yaml in de project root:

yaml
# .rr.yaml
version: "3"

server:
  command: "php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000"
  relay: pipes

http:
  address: 0.0.0.0:8000
  middleware: ["headers", "gzip"]
  pool:
    num_workers: 8
    max_jobs: 500
    supervisor:
      max_worker_memory: 128

De max_worker_memory instelling (in MB) beëindigt workers die geheugenlimieten overschrijden, wat een extra veiligheidsnet biedt naast max_requests. Voor teams met gevestigde CI-pipelines en bestaande PHP-FPM infrastructuur biedt RoadRunner het soepelste migratiepad.

Swoole: Maximale Throughput met Coroutine-concurrency

Swoole opereert als PHP-extensie die de standaard request-lifecycle vervangt door een event-driven, coroutine-capable runtime. Het biedt features die niet beschikbaar zijn in andere servers: concurrent task-uitvoering, ticks en intervals, en een in-memory cache met 2 miljoen operaties per seconde throughput.

bash
# Installeer Swoole via PECL
pecl install swoole

# Voeg toe aan php.ini
echo "extension=swoole.so" >> $(php --ini | grep "Loaded Configuration" | cut -d: -f2 | xargs)/php.ini

# Installeer Octane met Swoole
composer require laravel/octane
php artisan octane:install --server=swoole

# Start met task workers voor concurrent operaties
php artisan octane:start --server=swoole --workers=8 --task-workers=6

Swoole's concurrent task-uitvoering handelt parallelle I/O-operaties af binnen één enkel request:

app/Http/Controllers/DashboardController.phpphp
use App\Models\User;
use App\Models\Order;
use App\Models\Analytics;
use Laravel\Octane\Facades\Octane;

class DashboardController extends Controller
{
    public function index()
    {
        // Voer drie queries concurrent uit in plaats van sequentieel
        [$users, $orders, $analytics] = Octane::concurrently([
            fn () => User::active()->count(),
            fn () => Order::today()->sum('total'),
            fn () => Analytics::hourly()->get(),
        ]);

        return view('dashboard', compact('users', 'orders', 'analytics'));
    }
}

Zonder Octane::concurrently() worden deze drie queries sequentieel uitgevoerd: 50ms + 30ms + 40ms = 120ms totaal. Met concurrent uitvoering is de totale tijd gelijk aan de traagste query: 50ms. De --task-workers flag bepaalt hoeveel concurrent operaties tegelijkertijd kunnen draaien over alle request workers.

Swoole-exclusieve Features

Concurrent tasks, ticks, intervals, Octane cache en Swoole tables vereisen de Swoole-extensie. FrankenPHP en RoadRunner ondersteunen deze features niet. Evalueer of de applicatie deze nodig heeft voordat wordt gecommitteerd aan Swoole's operationele complexiteit.

Memory Leak Preventie: Stateless Code Schrijven

Octane's performance komt van persistent state, wat de primaire uitdaging creëert: code die prima werkte onder PHP-FPM kan catastrofale memory leaks veroorzaken onder Octane. De applicatie-instantie overleeft tussen requests, dus statische properties, singletons en globale state accumuleren.

Drie patronen veroorzaken de meeste memory leaks:

Statische arrays die onbegrensd groeien:

php
// FOUT: Memory leak - array groeit met elk request
class MetricsCollector
{
    public static array $data = [];

    public static function record(string $metric): void
    {
        self::$data[] = $metric; // Wordt nooit geleegd tussen requests
    }
}

// CORRECT: Gebruik request-scoped storage of externe systemen
class MetricsCollector
{
    public function record(string $metric): void
    {
        Redis::lpush('metrics', $metric); // Externe storage
    }
}

Singletons die request-specifieke data vasthouden:

php
// FOUT: Eerste request's user lekt naar volgende requests
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext($app['request']->user());
});

// CORRECT: Gebruik closures voor uitgestelde resolutie
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext(fn () => $app['request']->user());
});

Container en request injectie in constructors:

php
// FOUT: Vangt verouderde container/request
class PaymentService
{
    public function __construct(
        private Application $app,
        private Request $request
    ) {}
}

// CORRECT: Injecteer via method parameters of gebruik helpers
class PaymentService
{
    public function processPayment(Request $request): void
    {
        $user = $request->user();
        $config = config('services.stripe.key'); // Globale helper, altijd actueel
    }
}

De globale helpers app(), request() en config() retourneren altijd actuele waarden. Ze gebruiken in plaats van constructor-injectie omzeilt de meeste singleton-gerelateerde leaks.

Productie Deployment Patronen

Octane-servers hebben proces-supervisie nodig om te herstarten bij crashes. Supervisor handelt dit betrouwbaar af:

ini
; /etc/supervisor/conf.d/octane.conf
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/octane.log
stopwaitsecs=3600

Voor deployments moeten Octane workers herladen worden om nieuwe code op te pikken. Het octane:reload commando handelt dit graceful af, wachtend tot in-flight requests voltooid zijn voordat workers worden gerecycled:

bash
# In deployment script (na git pull, composer install, etc.)
php artisan octane:reload

Nginx zit voor Octane om statische assets te serveren en SSL te termineren:

nginx
# /etc/nginx/sites-available/app.conf
upstream octane {
    server 127.0.0.1:8000;
    keepalive 32;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/app/public;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        try_files $uri $uri/ @octane;
    }

    location @octane {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection "";
        proxy_pass http://octane;
    }
}

De keepalive directive onderhoudt persistente verbindingen tussen Nginx en Octane, wat TCP-handshake overhead vermindert voor proxied requests.

Klaar om je Laravel gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Beslisboom voor Serverselectie

De keuze tussen FrankenPHP, RoadRunner en Swoole hangt af van operationele beperkingen en applicatievereisten:

VereisteAanbevolen Server
Eenvoudigste setup, gecontaineriseerde deploymentFrankenPHP
HTTP/3 ondersteuning out-of-the-boxFrankenPHP
Geen PHP-extensie afhankelijkhedenFrankenPHP of RoadRunner
Maximale proces-isolatieRoadRunner
Gevestigde PHP-FPM infrastructuurRoadRunner
Concurrent I/O binnen requestsSwoole
In-memory caching (2M ops/sec)Swoole
Ticks, intervals, background tasksSwoole
Swoole tables voor gedeelde stateSwoole

Voor teams die nieuwe projecten starten in 2026 biedt FrankenPHP de beste balans tussen eenvoud en mogelijkheden. Migratie van bestaande applicaties werkt het beste met RoadRunner vanwege de proces-isolatie en het vertrouwde deployment-model. Swoole is geschikt voor high-throughput APIs die profiteren van coroutine-concurrency en Swoole-specifieke features nodig hebben.

Sollicitatievragen over Laravel Octane

Technische sollicitatiegesprekken behandelen steeds vaker Octane naarmate high-traffic Laravel applicaties het adopteren. Veelgestelde vragen en waar interviewers op letten:

"Hoe bereikt Octane zijn performance-winst?"

Het verwachte antwoord: Octane boot Laravel één keer per worker en hergebruikt die instantie voor requests, waardoor de 15-40ms bootstrap-kosten bij elk request worden geëlimineerd. Kandidaten moeten vermelden dat de register en boot methodes van service providers één keer per worker draaien, niet per request.

"Wat veroorzaakt memory leaks in Octane-applicaties?"

Sterke antwoorden identificeren drie bronnen: statische arrays die data accumuleren, singletons die request-specifieke state vastleggen, en constructor-injectie van container- of request-objecten. Kandidaten moeten uitleggen dat de oplossing het gebruik van closures voor uitgestelde resolutie of het doorgeven van data via method parameters inhoudt.

"Wanneer zou je Swoole kiezen boven RoadRunner?"

Swoole's voordelen zijn coroutine-concurrency via Octane::concurrently(), de snelle Octane cache, en features zoals ticks en intervals. De afweging is operationele complexiteit: Swoole vereist het beheren van een PECL-extensie, terwijl RoadRunner als Go-binary wordt geleverd. Voor CRUD-applicaties zonder concurrent I/O-behoeften is RoadRunner eenvoudiger te beheren.

"Hoe handel je deployments af met Octane?"

De deployment-sequentie: stop met het accepteren van nieuwe verbindingen, wacht tot in-flight requests voltooid zijn, herlaad workers met nieuwe code. Het php artisan octane:reload commando handelt dit af. Kandidaten moeten Supervisor of systemd noemen voor proces-supervisie en Nginx of Caddy als reverse proxy.

Monitoring en Profiling van Octane-applicaties

Geheugen-monitoring wordt kritisch onder Octane. Workers zijn persistent, dus geheugengroei duidt op leaks in plaats van normale request-overhead. Zowel Laravel Pulse als Telescope werken met Octane en bieden request-level profiling.

app/Providers/AppServiceProvider.phpphp
use Laravel\Octane\Events\RequestReceived;
use Laravel\Octane\Events\RequestTerminated;

public function boot(): void
{
    Event::listen(RequestReceived::class, function ($event) {
        $event->sandbox->instance('request.memory.start', memory_get_usage());
    });

    Event::listen(RequestTerminated::class, function ($event) {
        $start = $event->sandbox->make('request.memory.start');
        $delta = memory_get_usage() - $start;
        
        if ($delta > 1024 * 1024) { // Meer dan 1MB groei
            Log::warning('Hoge geheugen delta', [
                'path' => $event->request->path(),
                'delta_mb' => round($delta / 1024 / 1024, 2),
            ]);
        }
    });
}

Deze event listener logt requests die geheugen met meer dan 1MB verhogen, wat helpt bij het identificeren van endpoints die optimalisatie nodig hebben. Voor productie-monitoring bieden externe APM-tools zoals Datadog of New Relic worker-level zichtbaarheid.

Integratie van Octane met Queues en Horizon

Octane handelt HTTP-requests af; Laravel Horizon beheert queue workers. De twee opereren onafhankelijk en vullen elkaar aan. Zware verwerking hoort in queue jobs, wat Octane workers responsief houdt.

app/Http/Controllers/ReportController.phpphp
use App\Jobs\GenerateReport;

class ReportController extends Controller
{
    public function generate(Request $request)
    {
        // Dispatch naar queue in plaats van de Octane worker te blokkeren
        GenerateReport::dispatch($request->user(), $request->input('parameters'));

        return response()->json(['status' => 'processing']);
    }
}

Kernpunten over Laravel Octane in 2026

  • Octane 2.19 ondersteunt drie servers: FrankenPHP (eenvoudigste), RoadRunner (meest stabiel), en Swoole (meeste features)
  • Performance-winst komt van het elimineren van per-request bootstrap; verwacht 2x tot 4x throughput-verbetering
  • Memory leaks ontstaan omdat worker state persistent is; vermijd statische arrays, constructor-geïnjecteerde requests, en singletons met request data
  • Gebruik --max-requests=500 om worker recycling te forceren voordat geheugendruk opbouwt
  • Swoole-exclusieve features zijn Octane::concurrently(), ticks, intervals, en de Octane cache
  • Deploy achter Nginx of Caddy met Supervisor voor proces-beheer
  • Profileer geheugengroei per request; delta's boven 1MB duiden op potentiële leaks
  • Queue zware werkzaamheden via Horizon; houd Octane workers voor snelle HTTP-responses

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Dagelijkse challenge

Zie jij de bug in Laravel?

Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Anthony Fillion-Maillet

Geschreven door

Anthony Fillion-Maillet

Oprichter van SharpSkill

Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.

Bijgewerkt op 11 september 2026

Tags

#laravel
#octane
#swoole
#roadrunner
#frankenphp
#performance
#php

Delen

Gerelateerde artikelen