php runtime and server environment
Advanced PHP Runtimes
Traditional PHP-FPM handles each request with a clean request lifecycle. The application boots, handles the request, returns a response, and request-local state is discarded. Advanced PHP runtimes often keep the application alive between requests.
That can improve performance, reduce repeated boot work, and enable worker-style features. It also changes the rules: memory, static state, service containers, database connections, and per-request data must be handled more carefully.
The main idea
With PHP-FPM, a simplified request looks like this:
request -> boot app -> handle request -> return response -> clean request state
With a worker runtime, it often looks more like this:
start worker -> boot app once -> handle request -> handle next request -> handle next request
Keeping the app warm can be faster, but any state accidentally kept in memory can leak from one request to another.
<?php
declare(strict_types=1);
final class RequestCounter
{
public static int $count = 0;
}
foreach (['first request', 'second request', 'third request'] as $request) {
RequestCounter::$count++;
echo $request . ': ' . RequestCounter::$count . PHP_EOL;
}
// Prints:
// first request: 1
// second request: 2
// third request: 3
In a normal short request this static value would disappear after the request. In a worker model, state like this can survive and surprise you.
FrankenPHP
FrankenPHP is a modern PHP application server built on Caddy. It can run traditional PHP applications and also supports worker mode for better performance.
It is attractive because it can combine web server, HTTPS, and PHP runtime concerns into a simpler deployment shape. The professional caution is the same as with other worker modes: code must be safe when the process handles more than one request.
RoadRunner
RoadRunner is an application server written in Go that runs PHP workers. It can handle HTTP, queues, jobs, gRPC, and other services depending on configuration.
RoadRunner is common in teams that want long-running PHP workers without using PHP-FPM for every request. It expects the PHP application to cooperate with the worker lifecycle.
Swoole and OpenSwoole
Swoole and OpenSwoole provide event-driven, coroutine-capable server features as PHP extensions. They can support high-concurrency servers, async-style I/O, timers, task workers, and WebSocket-style workloads.
They are powerful, but the programming model is further from classic request-response PHP. You must understand shared memory, coroutine safety, blocking calls, long-lived objects, and extension compatibility.
Laravel Octane
Laravel Octane runs Laravel applications using servers such as Swoole/OpenSwoole, RoadRunner, or FrankenPHP depending on setup. It keeps the Laravel application booted between requests to reduce repeated framework startup cost.
The main development concern is state leakage. Services that accidentally keep request data, authenticated users, tenant IDs, locale settings, or mutable singletons can cause bugs that would not happen under classic PHP-FPM.
What changes for developers
Advanced runtimes make these habits more important:
- avoid storing request-specific data in static properties or long-lived singletons
- reset per-request state after each request
- check database connections after idle time or failures
- avoid assuming constructors run for every request
- monitor memory growth over time
- restart workers during deploys
- test under the same runtime used in production
When they are worth considering
Advanced runtimes can help when application boot time is expensive, traffic is high, latency matters, or the application benefits from long-running worker features. They are not automatically better for every project.
For many junior roles, PHP-FPM knowledge is still the baseline. Advanced runtimes become valuable when you can explain both the performance benefit and the operational risks.
What you should be able to do
After this lesson, you should be able to explain how long-running PHP runtimes differ from PHP-FPM, name common runtime options, recognise state-leak risks, and understand why worker-mode applications need different testing and deployment habits.
Practice
Task: Identify Worker Runtime Risks
Write a short review for a team considering Laravel Octane, RoadRunner, FrankenPHP worker mode, or Swoole/OpenSwoole.
Requirements
- Explain the main performance benefit of a long-running runtime.
- List at least four risks that are different from classic PHP-FPM.
- Include one small PHP example showing state that survives across multiple handled requests.
- Include a short recommendation for when the team should stay with PHP-FPM.
Check your work
The review should help a junior developer understand that advanced runtimes are not just a faster drop-in switch.
Show solution
<?php
declare(strict_types=1);
final class CurrentTenant
{
public static ?string $id = null;
}
foreach (['tenant-a', 'tenant-b'] as $tenantId) {
CurrentTenant::$id = $tenantId;
echo 'Handling request for ' . CurrentTenant::$id . PHP_EOL;
}
echo 'State still held: ' . CurrentTenant::$id . PHP_EOL;
// Prints:
// Handling request for tenant-a
// Handling request for tenant-b
// State still held: tenant-b
The benefit is that the application can stay booted between requests, so each request does less repeated framework startup work.
The risks are different from classic PHP-FPM:
- static properties can keep request-specific data
- singletons can accidentally keep users, tenants, locales, or permissions
- memory can grow across many requests
- database connections may become stale
- constructors may not run for every request
- deploys need worker reloads so old code is not kept alive
The team should stay with PHP-FPM if the application is small, traffic is modest, the team has not measured a boot-time bottleneck, or the codebase has not been reviewed for worker-safe state. Advanced runtimes are useful, but they add a lifecycle that the team must understand and test.