FrankenPHP vs PHP-FPM: Discover the Right PHP Server for Your Project’s Scalability and Performance Needs

Hire a PHP developer for your project — click here.

by admin
frankenphp_vs_php_fpm_server_choice

FrankenPHP vs PHP‑FPM: which server should you choose?

You probably didn’t open this article in a vacuum.

Maybe you’re staring at a Dockerfile wondering whether to swap php:fpm for dunglas/frankenphp.
Maybe your team lead dropped “We should really look at FrankenPHP” into a meeting and then moved on like that wasn’t a bomb.
Or maybe you’re just tired of Nginx config archaeology at 1:30 in the morning.

Whatever brought you here: you’re in the right place.

Let’s talk, developer to developer, about FrankenPHP vs PHP‑FPM — not as abstract tools, but as two very different answers to the question:

“How do I want my PHP to live in production?”

Two very different mental models

Put benchmarks aside for a moment. Forget buzzwords.

The biggest difference between PHP‑FPM and FrankenPHP is the mental model they push you into.

PHP‑FPM: the classic two‑piece band

PHP‑FPM is the thing you’ve probably been running for years without thinking too much about it.

  • Web server (Nginx/Apache) receives HTTP.
  • It forwards the request over FastCGI to PHP‑FPM, which:
    • Maintains a pool of PHP processes.
    • Assigns a process to handle each request.
    • Tears the request down when it’s done.

Every request is basically: boot framework → run code → die gracefully.

It’s battle‑tested, boring in the best way, and fits perfectly with the traditional, stateless PHP model where every request is clean slate.

FrankenPHP: the integrated, “one binary” server

FrankenPHP is a different animal.

  • Built on Caddy (web server in Go).
  • Embeds the PHP interpreter directly in the web server.
  • You get one integrated application server, no FastCGI hop between Nginx and FPM anymore.

In classic mode, it behaves like PHP‑FPM: request comes in, PHP handles it, then resets state.
In worker mode, it becomes a long‑running PHP application server: your app boots once and lives in memory between requests, reusing the container, config, and most of the framework state.

That’s where things get interesting.

Performance: where FrankenPHP shines — and where it doesn’t

Let’s rip the band‑aid off: you’ve probably seen claims like “FrankenPHP is 3x faster than PHP‑FPM.”

There’s a truth in there, and a trap.

Classic mode vs PHP‑FPM: not the explosion you might expect

When FrankenPHP runs in classic mode, it’s mostly removing the “Nginx ↔ PHP‑FPM” FastCGI hop and some process overhead.

Multiple benchmarks show:

  • FrankenPHP classic vs PHP‑FPM: performance is very close, often within a couple of percent in either direction.
  • One detailed test found Nginx + PHP‑FPM to be roughly 1.3% faster than FrankenPHP classic mode — essentially a rounding error for real apps.

That sounds almost… disappointing. But it’s important.

If you’re expecting to slap FrankenPHP classic into your stack and magically get 4x throughput, you’ll be underwhelmed. The honest conclusion from several benchmarks is:

Your application’s architecture matters more than the choice between PHP‑FPM and FrankenPHP in classic mode.

So why is everyone excited?

Worker mode: the “my framework boots once” revolution

The excitement is about worker mode.

Imagine a typical modern PHP app:

  • Laravel, Symfony, or some custom framework.
  • It spends a huge chunk of time on each request just booting:
    • Loading the framework.
    • Building the service container.
    • Loading config, routes, providers, etc.

PHP‑FPM pays that boot cost for every single request.

In FrankenPHP worker mode, your application:

  • Boots once.
  • Lives in memory.
  • Serves many requests with the same long‑running workers.

Benchmarks for worker mode often show:

  • 3–4x more requests per second vs Nginx + PHP‑FPM on framework‑heavy apps.
  • Much lower typical latency (e.g. 45ms down to ~8ms for similar workloads).
  • Even more dramatic gains under high concurrency in some tests.

Is that guaranteed? No. Benchmarks are always a little bit of a lie.
But the pattern is real: if your bottleneck is framework bootstrap, worker mode is a game‑changer.

One more complication: the tail

Performance isn’t just average latency and RPS.

Some deeper analysis of classic-mode benchmarks showed:

  • FrankenPHP can sometimes have worse 99th percentile latency than PHP‑FPM, even when average metrics look similar.
  • In other cases, misconfigured setups make either one look unfairly bad.

You know the rule: never trust a single benchmark.
If your business depends on response time, you benchmark your actual app on your infrastructure.

Still, as a mental rule of thumb:

  • Classic mode FrankenPHP ≈ PHP‑FPM in speed.
  • Worker mode FrankenPHP > PHP‑FPM for framework‑heavy, CPU‑bound workloads.
  • If your app is I/O‑bound (DB, APIs, queues), you gain less — the bottleneck is elsewhere.

Features and ecosystem: where each one feels at home

You’re not just choosing performance. You’re choosing a way of working.

What PHP‑FPM still does extremely well

PHP‑FPM is the quiet, reliable admin of the PHP world. It shines when you need:

  • Shared hosting / multi‑tenant setups
    It’s what the majority of hosting providers use.
    If you’re managing many sites, isolation via processes and pools is a feature, not a bug.

  • Maximum compatibility
    Old WordPress, legacy Symfony 3, bespoke frameworks, random “client’s uncle wrote this in 2011” apps — PHP‑FPM runs them all without asking for refactors.

  • Mature tooling & muscle memory
    Everyone has docs, Ansible roles, Terraform modules, StackOverflow answers for Nginx + PHP‑FPM.
    When something goes wrong at 3 AM, the familiarity is comforting.

  • Strong isolation via processes
    Each PHP‑FPM worker is a process. If one leaks memory or goes weird, it dies alone.
    For some teams, that safety net is non‑negotiable.

What FrankenPHP brings to the table

FrankenPHP, especially on a greenfield project, feels like joining the current decade.

It gives you:

  • Integrated server (Caddy + PHP in one)
    No separate Nginx and FPM. One binary, one config, fewer moving parts.

  • Modern HTTP features out of the box

    • HTTP/3
    • Automatic HTTPS / TLS via Caddy
    • Early Hints (103)
    • Built‑in support for real‑time stuff via Mercure in some setups
  • Worker mode for long‑running PHP
    You get “application server” behavior similar to RoadRunner or Swoole, but with a strong focus on staying compatible with mainstream PHP frameworks.

  • Simplified deployment for containers
    Especially in Docker/Kubernetes environments:

    • One container does web + PHP.
    • Fewer network hops.
    • Easier to reason about autoscaling and health checks.

But — and this is important — moving into worker mode is not zero‑effort.

The hidden cost: state, statics, and the long‑running beast

Traditional PHP (with PHP‑FPM) gives you a gift you might not even notice most days:

Every request starts with clean memory.

If you forget to reset a static property, it dies with the request.
If some library does something weird with globals, it gets wiped.

With FrankenPHP worker mode, your PHP lives longer:

  • Objects can persist across requests.
  • Static variables keep values.
  • Singletons stay truly single.

That’s how you get the performance gains. But it also means:

  • Libraries that assume “stateless per request” can cause subtle bugs.
  • Poorly written code can leak memory across requests.
  • You need to be more intentional about resetting state between requests.

You might never forget the first time you see a user get another user’s data because some shared service wasn’t properly reset in a long‑running worker.

That’s when you realize: worker mode is powerful, but it asks you to take PHP more seriously as a long‑running platform.

If you use Laravel Octane or similar tools, this will feel familiar. FrankenPHP is playing in that same space, just with its own architecture and Caddy base.

Concrete scenarios: what should you choose?

It’s late, you have a real project, not a theoretical one. Let’s look at some situations.

Scenario 1: small to mid‑size app, no big performance pain

You’re running:

  • A typical business app.
  • Maybe a few thousand users.
  • Nothing is on fire. You’re on Nginx + PHP‑FPM or Apache + PHP‑FPM.

You care more about reliability than chasing every microsecond.

In this world, the honest answer is:

  • Stick with PHP‑FPM, or
  • Use FrankenPHP in classic mode if:
    • You like Caddy.
    • You want simpler config.
    • You want HTTP/3 and auto‑TLS without extra setup.
See also
Unlock the Power of Laravel: Essential Guide to Crafting Your First Package with Confidence

You don’t have to chase worker mode here. It’s perfectly okay to choose peace of mind over complexity.

Scenario 2: new greenfield project with modern stack

Fresh Symfony 7 or latest Laravel. You’re building:

  • A SaaS product.
  • A complex internal system.
  • An API that’s hammered hard in production.

You’re using Docker or Kubernetes. You’re comfortable iterating on your architecture.

In this case:

  • FrankenPHP becomes very attractive.
  • You can:
    • Start in classic mode for maximum compatibility.
    • Move to worker mode once you’re confident your app behaves well in long‑running processes.
  • You get:
    • Cleaner container setups.
    • Modern HTTP/3 and TLS with almost no work.
    • A path to serious performance gains without switching languages.

Scenario 3: high‑traffic, framework‑heavy app where PHP is clearly the bottleneck

You’ve already:

  • Tuned PHP‑FPM workers.
  • Enabled opcache and preloading.
  • Optimized queries.
  • Added caching layers.

And still, PHP CPU is loaded, and bootstrapping your framework is expensive.

This is exactly where FrankenPHP worker mode shines.

The potential benefits:

  • Much higher throughput.
  • Lower median latency.
  • More efficient CPU usage (less time wasted on bootstrapping).

You will, however, pay with:

  • Extra testing for long‑running behavior.
  • Need to document rules for your team (“no static caches without reset”, etc.).
  • A steeper learning curve for debugging.

But if this app keeps your company running, it’s often worth the leap.

Scenario 4: legacy, multi‑tenant, messy reality

You’re running:

  • Many apps on the same server or cluster.
  • Different PHP versions.
  • Some are ancient WordPress or custom CMSes.
  • You don’t have the luxury of refactoring everything.

In this reality:

  • PHP‑FPM is still your best friend.
  • You get:
    • Strong process isolation.
    • Separate FPM pools per app.
    • Clear resource limits per site.

Could FrankenPHP run some of these? Probably.
Would it simplify your life? Not necessarily.

Sometimes, boring is the right choice.

Devops and operations: life on each side

Let’s zoom out from code for a moment.

Picture yourself in the server room, or staring at Grafana dashboards at 23:47, coffee cold, eyes tired.

How does each option feel then?

PHP‑FPM in production

You’ve seen this movie:

  • Nginx (or Apache) in front.
  • PHP‑FPM pool(s) behind.
  • You monitor:
    • CPU, RAM.
    • FPM queue length.
    • 502s from Nginx if FPM dies.

You scale by:

  • Adjusting FPM worker counts.
  • Adding more servers.
  • Maybe adding a dedicated load balancer.

When something breaks:

  • Logs are split: web server logs here, PHP logs there.
  • But you already know where to look. You’ve done this for years.

It’s a very operationally mature world. There are known best practices, countless guides, and many people who’ve seen every failure mode before.

FrankenPHP in production

With FrankenPHP:

  • Web server and PHP runtime live in one process.
  • Fewer moving parts, but also a new mental model.
  • Monitoring shifts more towards:
    • Thread counts (or workers).
    • Memory usage per process.
    • Behavior of long‑running workers if you’re using worker mode.

In Docker:

  • A FrankenPHP container is often simpler than “Nginx + PHP‑FPM” combo images.
  • Fewer layers of config and fewer processes to orchestrate.

But you’re also:

  • On a newer, evolving piece of technology.
  • Reading newer docs.
  • Navigating less battle‑tested edge cases.

If your team likes modern tooling and doesn’t fear reading GitHub issues to understand behavior, this is acceptable. If your team values extreme predictability above all, it’s a trade‑off to consider carefully.

The people side: team, skills, and habits

Tools don’t exist in isolation. They live inside teams.

When you choose FrankenPHP vs PHP‑FPM, you’re indirectly making choices about:

  • What your juniors will learn first.
  • Which late‑night problems your seniors will be paged for.
  • How much your team thinks of PHP as:
    • “A script engine for requests” vs
    • “A long‑running application platform.”

A few questions you might quietly ask yourself:

  • Does my team have experience with long‑running PHP (Octane, RoadRunner, Swoole)?
  • Is there someone who actually wants to own the complexity of worker mode?
  • If that person leaves, will the rest of the team be comfortable maintaining it?
  • Do we prefer innovation in the app layer right now, or in the infrastructure layer?

Sometimes the “technically best” choice is not the best choice for your team’s current season.

How this plays with jobs and hiring

Since we’re on a platform focused on PHP people — finding jobs, hiring specialists, staying in the ecosystem — there’s another layer.

FrankenPHP is still young compared to PHP‑FPM, but we can already see some emerging patterns in the labor market:

  • PHP‑FPM is table stakes.

    • If you’re a PHP backend dev, you’re expected to at least understand the basics of FPM pools, Nginx fastcgi config, opcache, etc.
    • For companies, this means you have a huge talent pool already familiar with your stack.
  • FrankenPHP experience is a differentiator (for now).

    • Developers who’ve deployed FrankenPHP in worker mode and handled real‑world traffic are still relatively rare.
    • For candidates, experience with FrankenPHP signals:
      • Comfort with modern runtime ideas.
      • Exposure to performance tuning beyond “add more caching”.
    • For companies, adopting FrankenPHP might attract developers who want to work with modern PHP runtimes instead of just “legacy LEMP forever.”

If you’re updating your resume on Find PHP, having a concrete story like:

  • “Migrated Symfony app from Nginx + PHP‑FPM to FrankenPHP worker mode, reduced p95 latency from 120ms to 35ms under peak load.”

…is the kind of line that makes hiring managers pause and think, “Okay, this person cares about runtime architecture, not just controller code.”

The quiet middle ground: starting simple, evolving later

One of the most pragmatic paths I’ve seen teams take looks like this:

  1. Start with what you understand.

    • If that’s PHP‑FPM: start there.
    • If you’re already comfortable with Caddy and like the FrankenPHP story: start FrankenPHP in classic mode.
  2. Instrument your app.

    • Measure:
      • response times,
      • CPU usage,
      • where time is spent (DB, external APIs, PHP boot).
    • Don’t guess; let the data speak.
  3. Ask: is PHP bootstrapping the bottleneck?

    • If your traces show a huge chunk of time just loading the framework every request, you’re a candidate for worker mode — FrankenPHP or otherwise.
  4. If yes, experiment with FrankenPHP worker mode… on a branch.

    • Deploy it to staging.
    • Run realistic load tests.
    • Watch memory.
    • Look for subtle state bugs.
  5. Move gradually.

    • Some apps might never need worker mode.
    • Some might go all‑in.
    • Both outcomes are okay.

In other words: you don’t have to choose “team FrankenPHP” or “team PHP‑FPM” as a matter of ideology. You can choose per project, per phase, even per service.

A simple decision cheat‑sheet

If we boil everything down to one screen you can keep open next to your terminal, it might look like this:

  • Choose PHP‑FPM when:

    • You’re on shared hosting or multi‑tenant setups.
    • You’re running lots of legacy apps.
    • You need maximum stability and familiarity.
    • Your team isn’t ready to deal with long‑running request workers.
    • Your current performance is “good enough.”
  • Choose FrankenPHP (classic mode) when:

    • You want to simplify ops using Caddy + embedded PHP.
    • You like the idea of “one binary server”.
    • You want HTTP/3 and automatic TLS out of the box.
    • You want a path to worker mode later, but you’re not ready yet.
  • Choose FrankenPHP (worker mode) when:

    • You’ve measured that framework boot is a major cost.
    • You’re building a high‑traffic API or SaaS.
    • Your team can handle debugging long‑running workers.
    • You’re comfortable treating PHP as an application server, not just a script engine.

The real question isn’t what to run — it’s how you want to grow

You’re probably reading this in between tasks.

Maybe a CI pipeline is finishing.
Maybe production is calm for once and you’re letting your mind wander toward “how can we do this better?”

FrankenPHP vs PHP‑FPM is a technical question, sure. But underneath it, there’s something softer:

  • Do you want to keep your PHP world predictable, well‑known, and stable?
  • Or are you at a point where you’re ready to accept new complexity for the sake of new capabilities?

There’s no moral high ground here.

Some of the healthiest teams I know are still on PHP‑FPM, shipping real things, sleeping well at night.
Some of the most energized ones are experimenting with FrankenPHP, RoadRunner, Swoole — stretching PHP into shapes it wasn’t originally built for, and loving the challenge.

If anything, that’s what I like about this ecosystem right now.

We have room for the quietly reliable and the wildly ambitious, side by side.

So when you next stare at your Dockerfile, or your job ad, or that long‑lived Symfony app that’s starting to feel slow under load, maybe the choice isn’t “old vs new,” but “what kind of problems do we want to be solving this year?”

Whatever you pick — PHP‑FPM or FrankenPHP, classic or worker — the important thing is that it helps you keep building, calmly, in that soft glow of your monitor, one careful decision at a time.
перейти в рейтинг

Related offers