FrankenPHP ist ein PHP-Applikationsserver auf Basis des Go-Webservers Caddy, der PHP-Ausführung und Webserver in einer einzigen Binary vereint und über seinen Worker-Mode den klassischen Bootstrap-Overhead von PHP-FPM eliminiert. Für Frameworks wie Laravel bedeutet das: Die Anwendung bootet einmal und bleibt danach im Speicher, statt bei jedem Request neu zu starten. In Kombination mit Laravel Octane gilt FrankenPHP heute als eine der performanteren PHP-Server-Optionen.
Als Laravel-Agentur mit Fokus auf professionelle Webentwicklung beschäftigen wir uns bei mindtwo täglich mit der Performance-Optimierung von PHP-Anwendungen, von klassischem Caching bis zu modernen Server-Architekturen. Dieser Artikel ordnet ein, wie FrankenPHP technisch funktioniert, wie es sich zu Alternativen wie Swoole und RoadRunner verhält und wann sich der Umstieg tatsächlich lohnt.
Warum FrankenPHP klassisches PHP-FPM herausfordert
Wer eine PHP-Anwendung seit Jahren betreibt, kennt das Muster: Jede einzelne HTTP-Anfrage startet bei null. In einem klassischen PHP-FPM-Setup durchläuft jeder Request den kompletten Anwendungs-Bootstrap neu, mit Autoloading, Service-Container, Konfigurationsdateien und Routing-Tabellen. Das Framework "erwacht" tausendfach am Tag, nur um nach wenigen Millisekunden wieder zu "sterben".
Dieser Kaltstart-Kreislauf ist über Jahrzehnte gewachsen, weil er ein entscheidendes Problem elegant löst: Isolation. Jeder Request bekommt einen komplett frischen Zustand, nichts „leakt“ von einem Request in den nächsten. Der Preis dafür ist Performance. Gerade bei komplexen, containerlastigen Frameworks wie Laravel oder Symfony macht sich der wiederholte Bootstrap deutlich bemerkbar.
Wer sich bereits mit klassischer PHP-Performance-Optimierung beschäftigt hat, kennt die üblichen Stellschrauben aus unserem Beitrag zu schnellen PHP-Websites und Anwendungen: OPcache, Redis-Caching, optimierte Datenbank-Queries und Framework-Level-Caching. Das sind wichtige und wirksame Maßnahmen, sie optimieren jedoch innerhalb eines bestehenden Server-Modells. Sie lösen nicht das strukturelle Problem, dass die Anwendung bei jedem Request komplett neu hochfährt.
Bisherige Lösungsansätze und ihre Grenzen
Bevor wir uns FrankenPHP im Detail ansehen, lohnt sich ein kurzer Blick darauf, was die PHP-Welt bereits unternommen hat, um den Bootstrap-Overhead zu reduzieren:
- OPcache: Cached den kompilierten Opcode von PHP-Dateien im Shared Memory, sodass nicht bei jedem Request neu parsed und kompiliert werden muss. Ein Pflicht-Feature für jede Produktionsumgebung, siehe auch unser Lexikon-Eintrag zu PHP OPcache.
- Preloading (seit PHP 7.4): Lädt definierte Klassen bereits beim Serverstart in den Speicher, statt sie pro Request erneut aufzulösen.
- FPM-Pool-Tuning: Anpassung von
pm.max_children,pm.max_requests& Co., um die Prozessverwaltung von PHP-FPM möglichst effizient auf die jeweilige Serverhardware abzustimmen.
Diese Maßnahmen sind wirkungsvoll, aber strukturell begrenzt. Sie reduzieren den Overhead pro Request. Sie verhindern aber nicht, dass der komplette Anwendungs-Zustand, also Service-Container, geladene Objekte und aufgebaute Verbindungen, nach jedem Request verworfen und beim nächsten Request neu aufgebaut wird. Genau hier setzt der fundamental andere Architekturansatz von FrankenPHP an.
FrankenPHP als Architektur-Antwort: Von Caddy zur Runtime
FrankenPHP wurde von Kévin Dunglas entwickelt und basiert auf Caddy, einem in Go geschriebenen, modernen Webserver, der unter anderem für automatisches HTTPS und native HTTP/2- sowie HTTP/3-Unterstützung bekannt ist. FrankenPHP integriert die PHP-Engine direkt als Modul in diesen Go-Server. Es ist also kein zusätzlicher Reverse Proxy vor einem separaten PHP-Prozess mehr nötig, sondern eine einzige Binary, die Webserver und PHP-Ausführung in sich vereint. Ein weiteres, in der Praxis oft unterschätztes Merkmal: FrankenPHP unterstützt als eine der wenigen PHP-SAPIs nativ HTTP-103-Early-Hints, mit denen Browser bereits kritische Ressourcen wie CSS oder Fonts laden können, während die eigentliche Antwort noch generiert wird.
Der entscheidende Unterschied zu klassischen Setups liegt nicht nur darin, dass PHP und Webserver in einem Prozess laufen, sondern wie dieser Prozess mit Anfragen umgeht. Und das führt uns direkt zum Kernstück von FrankenPHP: dem Worker-Mode.
Die Anatomie einer Anfrage im Worker-Mode
Der Worker-Mode ist der eigentliche Grund, warum FrankenPHP performancetechnisch in einer anderen Liga spielt als klassisches PHP-FPM. Statt für jeden Request einen neuen PHP-Prozess oder zumindest einen kompletten Bootstrap-Zyklus zu starten, funktioniert der Ablauf so:
- Einmaliger Boot: Beim Start eines Workers bootet die Anwendung, etwa ein Laravel-Projekt, genau einmal vollständig. Service-Container, Routing und Konfiguration werden einmal aufgebaut und bleiben danach im Speicher des Worker-Prozesses erhalten.
- Anfrage-Loop: Der Worker läuft in einer Endlosschleife und wartet auf eingehende Requests. Trifft ein Request ein, verarbeitet ihn die bereits initialisierte Anwendung direkt, ohne erneuten Bootstrap.
- Zustandsbereinigung zwischen Requests: Nach jedem Request sorgt FrankenPHP dafür, dass bestimmte globale Zustände zurückgesetzt werden, damit kein Request-Zustand in den nächsten "durchsickert". Superglobals wie
$_GET,$_POSToder$_SERVERwerden pro Request neu befüllt. - Wiederverwendung statt Neustart: Der Worker-Prozess bleibt über tausende Requests hinweg aktiv, bis er neu startet, etwa bei einem Deployment oder aus Stabilitätsgründen nach einer konfigurierbaren Anzahl von Requests.
Der Performance-Gewinn resultiert direkt aus Schritt 1: Der teure Bootstrap-Prozess entfällt für alle Requests außer dem allerersten pro Worker. Bei Frameworks mit umfangreichem Service-Container, wie Laravel, kann das den Großteil der Request-Zeit einsparen, die vorher für reines "Hochfahren" verbraucht wurde.
Diese Architektur bringt allerdings auch eine neue Verantwortung mit sich: Entwickler müssen aktiv darauf achten, dass kein Zustand versehentlich zwischen Requests bestehen bleibt, etwa durch statische Properties, Singleton-Instanzen mit Request-spezifischen Daten oder nicht zurückgesetzte Service-Container-Bindings. Diese Klasse von Bugs, im weiteren Sinne "Memory Leaks" genannt, existiert in klassischen PHP-FPM-Setups schlicht nicht, weil jeder Request ohnehin einen komplett frischen Prozess bekommt.
Reverse Proxy & Prozessmodell im Vergleich: FrankenPHP vs. PHP-FPM, Swoole und RoadRunner
FrankenPHP ist nicht der erste Versuch, PHP von seinem klassischen Request-Response-Zyklus zu lösen. Ein Vergleich mit etablierten Alternativen hilft, die Positionierung besser einzuordnen:
PHP-FPM (klassisch) Prozessmodell: Pool von PHP-Worker-Prozessen, die jeweils einen kompletten Bootstrap pro Request durchlaufen. Vorteil: maximale Isolation, extrem ausgereift, funktioniert mit praktisch jedem PHP-Code ohne Anpassung. Nachteil: Bootstrap-Overhead bei jedem Request, kein persistenter Anwendungszustand.
Swoole Eine PHP-Extension, die ein asynchrones, Event-Loop-basiertes Ausführungsmodell direkt in PHP einführt, inklusive Coroutinen. Swoole ist sehr performant, erfordert aber oft tiefere Eingriffe in den Anwendungscode und ein Umdenken in Richtung asynchroner Programmierung. Die Lernkurve ist entsprechend steiler.
RoadRunner Ein in Go geschriebener Application-Server, konzeptionell FrankenPHP nicht unähnlich: Auch hier läuft ein persistenter Worker-Prozess, der PHP-Anwendungen im Hintergrund am Leben hält. RoadRunner benötigt allerdings einen separaten Reverse Proxy davor, zum Beispiel Nginx, während FrankenPHP durch die Caddy-Integration Webserver und Anwendungsserver in einer Binary vereint.
FrankenPHP Kombiniert den Worker-Mode-Ansatz von RoadRunner mit einer nativen Webserver-Integration über Caddy, inklusive automatischem HTTPS und HTTP/3-Support. Zusätzlich unterstützt FrankenPHP auch einen klassischen, nicht-persistenten Modus, sodass ein sanfter Umstieg möglich ist, ohne sofort auf Worker-Mode-Kompatibilität des gesamten Codes angewiesen zu sein.
Der zentrale Unterschied zu Swoole liegt darin, dass FrankenPHP näher am klassischen PHP-Ausführungsmodell bleibt und weniger tiefgreifende Code-Anpassungen erfordert. RoadRunner ist architektonisch der nächste Verwandte, allerdings ohne die integrierte Webserver-Schicht.
FrankenPHP und Laravel Octane: Die Praxis-Kombination
Für Laravel-Projekte ist FrankenPHP besonders im Zusammenspiel mit Laravel Octane relevant. Octane bietet eine einheitliche Abstraktionsschicht für Application-Server wie Swoole, RoadRunner und FrankenPHP und übernimmt dabei die kritischen Aufgaben, die für den Worker-Mode-Betrieb notwendig sind:
- Zurücksetzen von Service-Container-Bindings zwischen Requests
- Behandlung von Singleton-Instanzen, die versehentlich Request-Zustand halten
- Bereitstellung von Lifecycle-Hooks (z. B.
Octane::tick()) für periodische Aufgaben im Worker
Die Kombination aus Octane und FrankenPHP gilt aktuell als eine der attraktiveren Optionen im Laravel-Ökosystem, da beide Komponenten gezielt für dieses Zusammenspiel entwickelt beziehungsweise erweitert wurden. Gerade für Teams, die ohnehin im Laravel-Umfeld arbeiten, ist der Umstieg auf FrankenPHP damit deutlich risikoärmer als ein Wechsel zu Swoole, da Octane die größten Fallstricke bereits abstrahiert.
Grenzen und Risiken: Wann FrankenPHP (noch) nicht die richtige Wahl ist
Trotz der überzeugenden Architektur ist FrankenPHP kein Selbstläufer für jedes Projekt. Einige Punkte, die vor einem Umstieg geprüft werden sollten:
- Legacy-Code mit globalem Zustand: Ältere Anwendungen, die stark auf globale Variablen, statische Properties oder unkontrollierte Singletons setzen, können im Worker-Mode zu subtilen Bugs führen, die in klassischen PHP-FPM-Setups nie aufgetreten wären.
- Speicherlecks: Da Worker-Prozesse über viele Requests hinweg laufen, akkumulieren sich kleine Speicherlecks, die bei kurzlebigen FPM-Prozessen irrelevant wären, im Worker-Mode zu einem echten Problem.
- Reifegrad des Ökosystems: FrankenPHP ist deutlich jünger als PHP-FPM. Nicht jedes PHP-Paket ist explizit auf Worker-Mode-Kompatibilität getestet, auch wenn sich die Situation seit 2025 kontinuierlich verbessert. Die mit FrankenPHP 2.0 eingeführte, überarbeitete Worker-API zeigt zudem, dass sich die API in diesem frühen Stadium noch grundlegend ändern kann. Bestehende Worker-Setups, etwa mit Symfony, mussten im Zuge dieses Updates teils angepasst werden.
- Debugging-Komplexität: Fehler, die nur nach hunderten Requests im selben Worker auftreten, sind schwerer zu reproduzieren als klassische, isolierte Request-Bugs.
Entscheidungsmatrix: Lohnt sich der Umstieg auf FrankenPHP?
FrankenPHP eignet sich besonders gut, wenn:
- die Anwendung unter spürbarem Bootstrap-Overhead leidet (komplexe Service-Container, viele Routen, umfangreiche Konfiguration)
- bereits Laravel mit Octane-Unterstützung im Einsatz ist oder geplant ist
- native HTTP/3-Unterstützung und vereinfachtes TLS-Handling (automatisches HTTPS via Caddy) gewünscht sind
- das Team bereit ist, Code auf global-state-Freiheit zu prüfen und entsprechend zu härten
FrankenPHP ist eher (noch) nicht die richtige Wahl, wenn:
- eine große Legacy-Codebasis existiert, deren Verhalten stark von Prozess-Isolation zwischen Requests abhängt
- Betriebssicherheit und jahrzehntelange Produktionsreife wichtiger sind als maximale Performance
- keine Kapazität besteht, den Code aktiv auf Worker-Mode-Tauglichkeit zu prüfen und zu testen
In vielen Fällen ist ein hybrider Ansatz sinnvoll: FrankenPHP zunächst in einer Staging-Umgebung oder für einen klar abgegrenzten Anwendungsteil zu testen, bevor eine vollständige Migration der Produktionsumgebung erfolgt.
Fazit
FrankenPHP steht exemplarisch für eine größere Bewegung in der PHP-Server-Landschaft: weg vom klassischen "jeder Request startet neu"-Modell, hin zu dauerhaft laufenden, gebooteten Anwendungsinstanzen. Die Kombination aus integriertem Go-basiertem Webserver, nativem HTTP/3 und dem Worker-Mode macht FrankenPHP zu einer der spannendsten Optionen, wenn es um PHP-Performance jenseits klassischer Caching-Strategien geht.
Gleichzeitig ist der Umstieg kein reiner Konfigurationsschalter. Wer von PHP-FPM auf FrankenPHP wechselt, wechselt implizit auch sein mentales Modell der Anwendungsarchitektur, weg von zustandsloser Isolation, hin zu bewusst verwaltetem, langlebigem Zustand. Für Teams, die diesen Schritt mit der nötigen technischen Sorgfalt angehen, bietet FrankenPHP in Kombination mit Laravel Octane ein sehr überzeugendes Performance-Potenzial für moderne PHP-Anwendungen. Sie möchten wissen, ob sich der Umstieg auf FrankenPHP für Ihr Projekt lohnt? Vereinbaren Sie ein kostenloses Erstgespräch mit unserem Team.