FPM-NGINX
fpm-nginx is the default BenchKit image. nginx takes the request, serves static files itself, and hands anything PHP to PHP-FPM over FastCGI. Both processes run in the same container under S6 Overlay, which restarts either one if it fails.
This is what most Laravel applications run in production, which is what makes it the right baseline for any comparison.
How it compares
Against FrankenPHP. FPM-NGINX boots the framework on every request. FrankenPHP can keep your application resident between requests in worker mode, which removes that bootstrap. FPM-NGINX is the more battle-tested of the two, and it is the honest starting point: measure here first, then measure what worker mode changes.
Against FPM-Apache. Both put PHP-FPM behind a web server over FastCGI, so the PHP side is identical. nginx handles high concurrency with lower memory per connection, so it usually comes out ahead on the load test. Choose Apache when you need Apache, not for throughput.
The concurrency model is the thing to keep in mind. A request occupies an FPM worker for its entire duration, including time spent waiting on a database or an API. That makes pm.max_children a hard ceiling on concurrency, and it is the single most common reason an FPM run looks worse than it should.
Run it
docker run -p 80:8080 \
-v benchkit-runs:/var/www/html/storage/app/runs \
serversideup/benchkit-laravel:latest
The latest tag is this variation. There is no suffix to add. To pin a PHP version, use the version as the tag — 8.4 is this variation on PHP 8.4. The full tag schema covers every combination.
Tune the pool before you compare
The default pool is not sized for your machine. Set it to at least your core count, then run:
services:
benchkit:
image: serversideup/benchkit-laravel:latest
ports:
- "80:8080"
environment:
PHP_FPM_PM_CONTROL: "dynamic"
PHP_FPM_PM_MAX_CHILDREN: "20"
volumes:
- benchkit-runs:/var/www/html/storage/app/runs
volumes:
benchkit-runs:
Use it as your baseline
Run your suite here first. Then run it on FrankenPHP and open both in Compare. Starting anywhere else makes the second number harder to interpret, because you have nothing ordinary to hold it against.