Laravel Octane 2026: Swoole, RoadRunner und Performance-Optimierung im Detail

Umfassender Leitfaden zu Laravel Octane 2.19 mit FrankenPHP, Swoole und RoadRunner. Serverauswahl, Memory-Leak-Prävention, parallele Aufgaben und produktionsreife Deployment-Strategien für hochperformante PHP-Anwendungen.

Laravel Octane Performance mit FrankenPHP, Swoole und RoadRunner

Laravel Octane revolutioniert die Performance von PHP-Anwendungen, indem das Framework persistent im Arbeitsspeicher gehalten wird. Version 2.19 (August 2026) unterstützt drei produktionsreife Server: FrankenPHP, Swoole und RoadRunner. Jeder Server erfüllt unterschiedliche betriebliche Anforderungen, und die falsche Wahl kostet entweder Performance oder Stabilität.

Schnellreferenz zur Serverauswahl

FrankenPHP: einfachste Einrichtung, natives HTTP/3, einzelne Binary. RoadRunner: bewährte Go-Binary, keine PHP-Erweiterungen erforderlich. Swoole: maximaler Durchsatz mit Coroutine-Concurrency, erfordert PECL-Erweiterungsmanagement.

Wie Octane den Bootstrap-Overhead eliminiert

Traditionelles PHP-FPM startet einen neuen Prozess pro Anfrage. Laravel bootet seinen Service-Container, lädt Konfigurationen, registriert Provider und löst Middleware bei jedem einzelnen HTTP-Aufruf auf. Octane kehrt dieses Modell um: Die Anwendung bootet einmal pro Worker und dieselbe Instanz verarbeitet tausende Anfragen sequenziell.

Der Performance-Gewinn entsteht durch das Entfernen wiederholter Arbeit. Eine typische Laravel 12-Anwendung verbringt 15 bis 40ms mit dem Bootstrapping bevor die Geschäftslogik ausgeführt wird. Mit Octane sinkt dieser Aufwand nach der ersten Anfrage auf null. Benchmarks auf identischer Hardware zeigen 2- bis 4-fache Durchsatzverbesserungen für API-Endpunkte, wobei der Unterschied mit zunehmender Anwendungskomplexität wächst.

config/octane.phpphp
return [
    'server' => env('OCTANE_SERVER', 'frankenphp'),
    
    // Workers verarbeiten HTTP-Anfragen
    'workers' => env('OCTANE_WORKERS', 8),
    
    // Workers nach N Anfragen sanft neustarten um Memory Bloat zu verhindern
    'max_requests' => env('OCTANE_MAX_REQUESTS', 500),
    
    // Task-Workers für Swoole-Concurrent-Operations
    'task_workers' => env('OCTANE_TASK_WORKERS', 6),
    
    // Maximale Ausführungszeit pro Anfrage in Sekunden
    'max_execution_time' => 30,
];

Die Einstellung max_requests fungiert als Sicherheitsventil. Selbst gut geschriebener Code kann über hunderte Anfragen Speicher akkumulieren. Ein Wert von 500 erzwingt einen Neustart der Worker bevor Speicherdruck problematisch wird.

FrankenPHP: Der Standard für neue Projekte 2026

FrankenPHP wird als einzelne Binary geliefert, gebaut auf Caddy und PHP. HTTPS-Zertifikate werden automatisch über Let's Encrypt verwaltet, HTTP/3 funktioniert direkt und es müssen keine PHP-Erweiterungen installiert werden. Laravels Installer und Produktionsbeispiele verwenden jetzt standardmäßig FrankenPHP.

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

# Server starten
php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=8000

Für containerisierte Deployments bietet FrankenPHP offizielle Docker-Images:

dockerfile
# Dockerfile
FROM dunglas/frankenphp

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

COPY . /app

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

Die Docker-Compose-Konfiguration für die Entwicklung aktiviert HTTPS und HTTP/3:

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 behandelt Worker-Neustarts sanft und integriert sich direkt in Caddys Middleware-System für komplexe Routing-Szenarien.

RoadRunner: Go-basierte Stabilität ohne Erweiterungsabhängigkeiten

RoadRunner kompiliert zu einer Go-Binary, die PHP-Worker-Prozesse verwaltet. Die Kommunikation mit PHP erfolgt über ein binäres Protokoll, wobei Worker-Management und HTTP-Handling in Go bleiben während Anwendungscode in PHP ausgeführt wird. Diese Architektur bietet Prozessisolierung: Ein abstürzender PHP-Worker beeinflusst weder den Go-Parent noch Geschwister-Worker.

bash
# Octane mit RoadRunner installieren
composer require laravel/octane spiral/roadrunner-cli spiral/roadrunner-http

php artisan octane:install --server=roadrunner

# RoadRunner-Binary herunterladen
./vendor/bin/rr get-binary

# Server starten
php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000

Die RoadRunner-Konfiguration befindet sich in .rr.yaml im Projektstammverzeichnis:

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

Die Einstellung max_worker_memory (in MB) beendet Worker, die Speichergrenzen überschreiten, und bietet ein zusätzliches Sicherheitsnetz über max_requests hinaus. Für Teams mit etablierten CI-Pipelines und bestehender PHP-FPM-Infrastruktur bietet RoadRunner den reibungslosesten Migrationspfad.

Swoole: Maximaler Durchsatz mit Coroutine-Concurrency

Swoole operiert als PHP-Erweiterung, die den Standard-Request-Lifecycle durch eine ereignisgesteuerte, coroutine-fähige Runtime ersetzt. Es bietet Funktionen, die in anderen Servern nicht verfügbar sind: parallele Task-Ausführung, Ticks und Intervalle sowie einen In-Memory-Cache mit 2 Millionen Operationen pro Sekunde Durchsatz.

bash
# Swoole via PECL installieren
pecl install swoole

# Zur php.ini hinzufügen
echo "extension=swoole.so" >> $(php --ini | grep "Loaded Configuration" | cut -d: -f2 | xargs)/php.ini

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

# Mit Task-Workern für parallele Operationen starten
php artisan octane:start --server=swoole --workers=8 --task-workers=6

Swooles parallele Task-Ausführung verarbeitet I/O-Operationen innerhalb einer einzelnen Anfrage gleichzeitig:

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()
    {
        // Drei Abfragen parallel statt sequenziell ausführen
        [$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'));
    }
}

Ohne Octane::concurrently() werden diese drei Abfragen sequenziell ausgeführt: 50ms + 30ms + 40ms = 120ms gesamt. Mit paralleler Ausführung entspricht die Gesamtzeit der langsamsten Abfrage: 50ms. Das Flag --task-workers steuert, wie viele parallele Operationen gleichzeitig über alle Request-Worker laufen können.

Nur-Swoole-Funktionen

Parallele Tasks, Ticks, Intervalle, Octane-Cache und Swoole-Tabellen erfordern die Swoole-Erweiterung. FrankenPHP und RoadRunner unterstützen diese Funktionen nicht. Es sollte evaluiert werden, ob die Anwendung diese benötigt, bevor man sich auf Swooles betriebliche Komplexität einlässt.

Memory-Leak-Prävention: Zustandslosen Code schreiben

Octanes Performance entsteht durch persistenten Zustand, was auch die Hauptherausforderung darstellt: Code, der unter PHP-FPM problemlos funktionierte, kann unter Octane katastrophale Speicherlecks verursachen. Die Anwendungsinstanz überlebt über Anfragen hinweg, sodass statische Properties, Singletons und globaler Zustand akkumulieren.

Drei Muster verursachen die meisten Speicherlecks:

Statische Arrays die unbegrenzt wachsen:

php
// FALSCH: Speicherleck - Array wächst mit jeder Anfrage
class MetricsCollector
{
    public static array $data = [];

    public static function record(string $metric): void
    {
        self::$data[] = $metric; // Wird zwischen Anfragen nie geleert
    }
}

// RICHTIG: Request-bezogenen Speicher oder externe Systeme verwenden
class MetricsCollector
{
    public function record(string $metric): void
    {
        Redis::lpush('metrics', $metric); // Externer Speicher
    }
}

Singletons die request-spezifische Daten halten:

php
// FALSCH: User der ersten Anfrage leckt in nachfolgende Anfragen
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext($app['request']->user());
});

// RICHTIG: Closures für verzögerte Auflösung verwenden
$this->app->singleton(UserContext::class, function ($app) {
    return new UserContext(fn () => $app['request']->user());
});

Container- und Request-Injection in Konstruktoren:

php
// FALSCH: Erfasst veralteten Container/Request
class PaymentService
{
    public function __construct(
        private Application $app,
        private Request $request
    ) {}
}

// RICHTIG: Via Methodenparameter injizieren oder Helper verwenden
class PaymentService
{
    public function processPayment(Request $request): void
    {
        $user = $request->user();
        $config = config('services.stripe.key'); // Globaler Helper, immer aktuell
    }
}

Die globalen Helper app(), request() und config() geben immer aktuelle Werte zurück. Ihre Verwendung statt Constructor-Injection umgeht die meisten singleton-bezogenen Lecks.

Produktions-Deployment-Muster

Octane-Server benötigen Prozessüberwachung zum Neustart bei Abstürzen. Supervisor erledigt dies zuverlässig:

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

Bei Deployments müssen Octane-Worker neu geladen werden, um neuen Code zu übernehmen. Der Befehl octane:reload erledigt dies sanft und wartet auf laufende Anfragen bevor Worker recycelt werden:

bash
# Im Deployment-Skript (nach git pull, composer install, etc.)
php artisan octane:reload

Nginx sitzt vor Octane, um statische Assets zu servieren und SSL zu terminieren:

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;
    }
}

Die keepalive-Direktive hält persistente Verbindungen zwischen Nginx und Octane aufrecht und reduziert TCP-Handshake-Overhead für proxied Requests.

Bereit für deine Laravel-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Entscheidungsbaum zur Serverauswahl

Die Wahl zwischen FrankenPHP, RoadRunner und Swoole hängt von betrieblichen Einschränkungen und Anwendungsanforderungen ab:

AnforderungEmpfohlener Server
Einfachste Einrichtung, containerisiertes DeploymentFrankenPHP
HTTP/3-Unterstützung direkt verfügbarFrankenPHP
Keine PHP-ErweiterungsabhängigkeitenFrankenPHP oder RoadRunner
Maximale ProzessisolierungRoadRunner
Etablierte PHP-FPM-InfrastrukturRoadRunner
Parallele I/O innerhalb von AnfragenSwoole
In-Memory-Caching (2M ops/sek)Swoole
Ticks, Intervalle, Hintergrund-TasksSwoole
Swoole-Tabellen für geteilten ZustandSwoole

Für Teams, die 2026 neue Projekte starten, bietet FrankenPHP die beste Balance zwischen Einfachheit und Leistungsfähigkeit. Die Migration bestehender Anwendungen funktioniert am besten mit RoadRunner aufgrund seiner Prozessisolierung und des vertrauten Deployment-Modells. Swoole eignet sich für Hochdurchsatz-APIs, die von Coroutine-Concurrency profitieren und Swoole-spezifische Funktionen benötigen.

Interviewfragen zu Laravel Octane

Technische Interviews decken zunehmend Octane ab, da hochfrequentierte Laravel-Anwendungen es übernehmen. Häufige Fragen und worauf Interviewer achten:

"Wie erreicht Octane seine Performance-Gewinne?"

Die erwartete Antwort: Octane bootet Laravel einmal pro Worker und verwendet diese Instanz für Anfragen wieder, wodurch die 15-40ms Bootstrap-Kosten bei jeder Anfrage eliminiert werden. Kandidaten sollten erwähnen, dass die register- und boot-Methoden der Service-Provider einmal pro Worker laufen, nicht pro Anfrage.

"Was verursacht Speicherlecks in Octane-Anwendungen?"

Starke Antworten identifizieren drei Quellen: statische Arrays, die Daten akkumulieren, Singletons, die request-spezifischen Zustand erfassen, und Constructor-Injection von Container- oder Request-Objekten. Kandidaten sollten erklären, dass die Lösung die Verwendung von Closures für verzögerte Auflösung oder die Übergabe von Daten über Methodenparameter beinhaltet.

"Wann würden Sie Swoole gegenüber RoadRunner wählen?"

Swooles Vorteile sind Coroutine-Concurrency via Octane::concurrently(), der Hochgeschwindigkeits-Octane-Cache und Funktionen wie Ticks und Intervalle. Der Kompromiss ist betriebliche Komplexität: Swoole erfordert das Management einer PECL-Erweiterung, während RoadRunner als Go-Binary geliefert wird. Für CRUD-Anwendungen ohne parallele I/O-Anforderungen ist RoadRunner einfacher zu betreiben.

"Wie handhaben Sie Deployments mit Octane?"

Die Deployment-Sequenz: neue Verbindungen nicht mehr akzeptieren, auf laufende Anfragen warten, Worker mit neuem Code neu laden. Der Befehl php artisan octane:reload erledigt dies. Kandidaten sollten Supervisor oder systemd für Prozessüberwachung und Nginx oder Caddy als Reverse Proxy erwähnen.

Monitoring und Profiling von Octane-Anwendungen

Speicherüberwachung wird unter Octane kritisch. Worker sind persistent, sodass Speicherwachstum auf Lecks hindeutet statt auf normalen Request-Overhead. Laravel Pulse und Telescope funktionieren beide mit Octane und bieten 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) { // Mehr als 1MB Wachstum
            Log::warning('Hoher Speicher-Delta', [
                'path' => $event->request->path(),
                'delta_mb' => round($delta / 1024 / 1024, 2),
            ]);
        }
    });
}

Dieser Event-Listener protokolliert Anfragen, die den Speicher um mehr als 1MB erhöhen, und hilft bei der Identifizierung von Endpunkten, die Optimierung benötigen. Für Produktions-Monitoring bieten externe APM-Tools wie Datadog oder New Relic Worker-Level-Sichtbarkeit.

Integration von Octane mit Queues und Horizon

Octane verarbeitet HTTP-Anfragen; Laravel Horizon verwaltet Queue-Worker. Beide operieren unabhängig und ergänzen sich. Schwere Verarbeitung gehört in Queue-Jobs, damit Octane-Worker reaktionsfähig bleiben.

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

class ReportController extends Controller
{
    public function generate(Request $request)
    {
        // An Queue delegieren statt den Octane-Worker zu blockieren
        GenerateReport::dispatch($request->user(), $request->input('parameters'));

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

Wichtige Erkenntnisse zu Laravel Octane 2026

  • Octane 2.19 unterstützt drei Server: FrankenPHP (einfachste), RoadRunner (stabilste) und Swoole (meiste Funktionen)
  • Performance-Gewinne entstehen durch Eliminierung des Per-Request-Bootstrap; 2- bis 4-fache Durchsatzverbesserung erwartet
  • Speicherlecks treten auf, weil Worker-Zustand persistent ist; statische Arrays, constructor-injizierte Requests und Singletons mit Request-Daten vermeiden
  • --max-requests=500 verwenden, um Worker-Recycling vor Speicherdruckaufbau zu erzwingen
  • Nur-Swoole-Funktionen umfassen Octane::concurrently(), Ticks, Intervalle und den Octane-Cache
  • Hinter Nginx oder Caddy deployen mit Supervisor für Prozess-Management
  • Speicherwachstum pro Request profilieren; Deltas über 1MB deuten auf potenzielle Lecks hin
  • Schwere Arbeit über Horizon in Queues auslagern; Octane-Worker für schnelle HTTP-Antworten reservieren

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Tägliche Challenge

Findest du den Bug in Laravel?

Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Anthony Fillion-Maillet

Geschrieben von

Anthony Fillion-Maillet

Gründer von SharpSkill

Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.

Aktualisiert am 11. September 2026

Tags

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

Teilen

Verwandte Artikel