Here’s Why FrankenPHP Worker Mode Saves Your Sanity
A lot of developers spend little to no time thinking about how our code gets from being code to something that can be interacted with by the consumers of our code. There are several large components that we can affect to improve the performance of this interaction. One of them that doesn’t get much discussion is how altering the HTTP server can make a huge difference in performance.
Traditionally, in the PHP space, we usually default to Apache or nginx, but recently, the FrankenPHP project has been released, which makes it much easier to deploy our code and potentially much faster.
In this article, we’ll explore why the traditional PHP request lifecycle creates performance bottlenecks, how FrankenPHP’s worker mode eliminates that overhead, and how to migrate an existing Laravel application to FrankenPHP.
The Problem with the Traditional PHP Request Cycle
One of the features that traditionally makes PHP easy to use is that it shares nothing between requests, and each time a request is made, everything starts from scratch. Because of this, we don’t need to worry about a variable being set in one request that affects the state of another request. But this comes with a downside.
Because we’re starting from zero every time, there are a lot of pieces that get repeated over and over again, like importing classes and configurations that could be reused if we didn’t use this architecture. In some cases, most of your request (that isn’t accessing a database) can be taken up by your framework of choice, loading itself into memory just for a small portion of it to be used.
Because of this, your servers work harder, your response times suffer, and your hosting bill grows.
FrankenPHP: A Modern Application Server
FrankenPHP takes a different approach. Built on top of the Caddy web server and written in Go, it embeds PHP directly into the server process.
Before we dive in, I want to mention that FrankenPHP has official support from the PHP Foundation, and this isn’t some experimental side project. It’s a production-ready solution with financial backing, so we can assume it’s not going to disappear next week or even next year. That matters when you’re choosing infrastructure for your applications.
FrankenPHP comes with a ton of cool features that make developing modern applications less painful. Some of these are because it’s built on the Caddy web server, and some of it is built into the FrankenPHP.
The ones that might be of most interest to you are:
- It automatically generates HTTPS certificates, which is a requirement of the modern web.
- It has built-in support for HTTP/2 and HTTP/3, which is going to massively improve the performance of your application
- It provides Early Hints support, which allows the browser to start downloading resources before the whole page has been rendered
- It provides graceful reloads for zero-downtime deployments
These alone provide improvements, but the real magic happens with worker mode.
With worker mode, your application boots once and stays in memory. Subsequent requests skip the entire bootstrap process and jump straight to handling the request. The difference can be dramatic. That framework of overhead you had earlier is gone, and your requests get supercharged.
To get this to work correctly, you generally need to set up your application to run in worker mode. If you’re using a framework like Laravel or Symfony, you just need to install a package that allows the framework to operate in worker mode, and then it should work out of the box.
Migrating a Laravel Application
Let’s walk through migrating an existing Laravel application to FrankenPHP. First, you’ll need the Laravel Octane package, which provides the worker logic:
composer require laravel/octane
php artisan octane:install
When prompted, select FrankenPHP as your server. The installer creates a configuration file at config/octane.php.
Depending on your configuration, you might need to make some additional tweaks, but generally, you just need to run.
php artisan octane:start --server=frankenphp
That’s it. Your Laravel application is now running with FrankenPHP worker mode. No Docker required, no complex configuration. The transition is remarkably smooth.
Deployment Flexibility
Depending on your needs, FrankenPHP offers several deployment options. In production, it’s generally best to run it as a standalone binary or using the official Docker images for containerized deployments. For local development, Laravel Octane handles everything seamlessly.
The standalone binary option is interesting because it’s unique to FrankenPHP. It creates a single executable file that contains the PHP runtime, the web server, and your application code. There’s no separate PHP installation required, so you can distribute your app easily without having to worry about version differences.
What to Watch Out For
Worker mode is powerful, but keeping PHP applications in memory introduces challenges you need to understand.
For example, because we’re reusing the same “instance” of PHP, we can run into issues with static variables not resetting correctly between requests. For example, in the code below, we’re keeping track of a counter, but the counter will be shared between requests.
<?php
class RequestCounter
{
public static int $count = 0;
// First request: returns 1
// Second request: returns 2 (not 1!)
// This state persists across requests
public static function increment(): int
{
return ++self::$count;
}
}
To solve these types of problems, you’ll need to take care to manually reset them as part of your application setup. You can also set the “max_requests” parameter to specify how many requests each worker will handle before it restarts.
What You Need To Know
- Traditional PHP bootstraps your entire application on every request, wasting significant CPU cycles.
- FrankenPHP worker mode boots once and keeps your application in memory for massive performance gains.
- Laravel Octane provides seamless integration with minimal configuration changes.
- Watch out for static properties that persist between requests.
- Use
max_requeststo restart workers periodically and prevent memory issues from compounding.



Leave a comment
Use the form below to leave a comment: