Milind Daraniya

Is PHP-FPM Still the Best Choice for Laravel in 2026?

Published August 26th, 2026 22 min read

For a long time, the standard Laravel production setup was very simple.

Nginx.

PHP-FPM.

Laravel.

MySQL.

Redis.

I have used this type of architecture many times.

And honestly, it works.

It is stable.

It is well understood.

Hosting providers support it.

Most PHP developers know how to troubleshoot it.

So when somebody tells me:

"You should replace PHP-FPM."

my first question is:

"Why?"

This is where things get interesting.

Because PHP application servers have changed a lot.

Laravel Octane introduced support for long-running application servers, and Laravel officially supports servers such as FrankenPHP, Swoole and RoadRunner. FrankenPHP in particular has become a very interesting option because it combines a modern web server with the PHP runtime and supports features such as worker mode, HTTP/2, HTTP/3 and automatic HTTPS.

So the question in 2026 is not really:

"Can PHP be fast?"

We already know it can.

The more interesting question is:

"Do we still need to run PHP applications in exactly the same way we did years ago?"

The traditional PHP request model

Let's first understand the setup most of us already know.

A typical application looks like:

Browser
   ↓
Nginx
   ↓
PHP-FPM
   ↓
Laravel
   ↓
Database / Redis

A request comes in.

Nginx receives it.

PHP-FPM handles the PHP request.

Laravel boots the application.

The framework loads configuration.

Services are resolved.

Routes are loaded.

Middleware runs.

The controller runs.

The response is generated.

Then that request finishes.

Another request comes.

The process starts again according to the PHP-FPM model.

This model has been extremely successful.

But there is also some repeated work.

Laravel is a large application

A Laravel application can have a lot of bootstrap work.

For example:

Framework
Configuration
Providers
Routes
Middleware
Packages
Services
Application Classes

Every request may have to initialize a significant amount of application state.

With normal PHP-FPM execution, this is part of the traditional request lifecycle.

Now imagine an application handling thousands or millions of requests.

That repeated startup work becomes something worth thinking about.

This is where Octane changes the model

Laravel Octane allows the application to run using long-lived application servers.

Instead of starting from a completely clean PHP application state for every request, the application can remain loaded in memory between requests.

The basic idea is:

Traditional

Request
↓
Boot Laravel
↓
Handle request
↓
End

Versus a long-running server:

Start
↓
Boot Laravel
↓
Keep application in memory
↓
Request
↓
Request
↓
Request
↓
Request

This can significantly change application performance characteristics.

Laravel officially describes Octane as a way to supercharge Laravel applications using application servers such as FrankenPHP, Swoole and RoadRunner.

FrankenPHP makes this especially interesting

FrankenPHP is a modern PHP application server built on top of Caddy.

What makes it interesting to me is that it combines several pieces into one modern application server.

It supports:

  • PHP
  • HTTPS
  • HTTP/2
  • HTTP/3
  • Worker mode
  • Static files
  • Compression
  • Modern web-server features

FrankenPHP's official documentation also provides direct Laravel integration through Octane.

This is important because the deployment model becomes simpler.

Instead of thinking:

Nginx
+
PHP-FPM
+
Configuration
+
Extra web-server setup

we can think about:

FrankenPHP
+
Laravel

Of course, production infrastructure can still be more complex.

But the architecture becomes interestingly compact.

Worker mode is the real difference

The part I find most interesting is worker mode.

The application boots once.

Then workers stay alive.

This means the framework does not need to be fully initialized from scratch for every request.

According to FrankenPHP's official documentation, its worker mode keeps the application in memory and is supported by Laravel through Octane.

This can be a major performance improvement for suitable applications.

But it also creates a new responsibility.

And that responsibility is often ignored.

Your application is now long-lived

Normal PHP developers are used to a very important assumption:

The request ends, so the PHP process ends its useful request state.

With a long-running worker, that assumption changes.

Your application can remain alive.

That means state can accidentally remain in memory.

For example:

class SomeService
{
    protected array $data = [];

    public function add($value)
    {
        $this->data[] = $value;
    }
}

If that service lives longer than a single request, the data may persist between requests depending on how the service is managed.

That can create very strange bugs.

This is why Octane requires a different mindset

When we move to a long-running application server, we need to think about:

  • Static properties
  • Singleton services
  • Global state
  • Cached objects
  • In-memory arrays
  • Request-specific data
  • Event listeners
  • Service container state

Something that was harmless in traditional PHP can become dangerous in a long-lived process.

Laravel's Octane documentation specifically warns developers about memory leaks and state that can persist between requests.

This is one of the biggest reasons I would not blindly move every Laravel project to Octane.

Performance is not magic

I have seen discussions where developers assume:

"Use Octane and the application will automatically become 10 times faster."

I don't think that is a good way to think about it.

Suppose my endpoint does this:

Request
↓
Laravel
↓
MySQL query
↓
External API
↓
Another MySQL query
↓
Redis
↓
Response

If the database query takes 500 ms, speeding up Laravel's application boot time may not solve the real problem.

This is why I always come back to:

Measure first.

If application bootstrap is a bottleneck, Octane can help.

If the database is the bottleneck, optimize the database.

If an external API takes one second, changing PHP-FPM may not make the API faster.

This is where developers sometimes optimize the wrong thing

Imagine:

Laravel boot time = 20 ms
Database = 400 ms
External API = 600 ms

And we switch to a faster application server.

Maybe we save:

10 ms

That is technically better.

But the user may still wait:

1 second

The architecture did not solve the actual bottleneck.

This is why performance engineering should always start with profiling.

FrankenPHP is not the only option

Laravel Octane supports multiple application servers.

The main options include:

FrankenPHP
Swoole
RoadRunner

All of them can support long-running PHP applications.

And this creates an interesting problem:

Which one is actually fastest?

The answer is:

It depends.

Recent 2026 benchmarks and production reports have produced different results between FrankenPHP, RoadRunner and Swoole. That is actually a useful lesson because benchmark results can change dramatically depending on the Laravel workload, configuration and test methodology.

So I would never choose an application server purely because someone posted a benchmark screenshot.

Benchmarks are useful, but your application is more important

Suppose someone tells me:

Server A = 100,000 requests/sec
Server B = 80,000 requests/sec

My next question is:

"Doing what?"

A benchmark with:

Hello World

does not tell me much about my ERP application.

My real application might have:

Authentication
Policies
Eloquent
Relationships
Events
Queues
Redis
Database
Third-party APIs
Logging

That workload is very different.

I want to test:

My application.

Not somebody else's benchmark.

Laravel Octane also changes how we think about queues

This is another useful point.

Our HTTP server and queue worker are separate concerns.

We could have:

FrankenPHP
↓
Laravel Web Requests

and:

Laravel Queue Workers
↓
Redis

This means adopting FrankenPHP does not mean replacing every part of the architecture.

We can introduce it where it provides value.

That is a good migration strategy.

You can use FrankenPHP without rewriting Laravel

This is probably the biggest reason I find it interesting.

We don't need to move from:

Laravel

to:

Some completely different framework

We can continue using:

Routes
Controllers
Models
Services
Jobs
Events
Policies

The application architecture can remain mostly the same.

The application server changes.

That makes experimentation much easier.

Docker makes this even easier

If we are already using Docker, FrankenPHP has an official Docker image.

The official Laravel/FrankenPHP documentation shows a simple Docker-based setup for running Laravel with FrankenPHP.

This is useful because we can test the architecture without rebuilding our entire server environment.

For example:

Docker
   ↓
FrankenPHP
   ↓
Laravel
   ↓
Redis
   ↓
MySQL

That makes local experimentation much easier.

It also supports modern web protocols

Another thing I like about FrankenPHP is that it is not simply:

"PHP-FPM with another name."

It is built on Caddy and supports HTTP/1.1, HTTP/2 and HTTP/3, along with automatic HTTPS and modern web-server features.

That means we get a more modern application-server approach around PHP.

For new systems, that is interesting.

But I would not replace Nginx everywhere

There is nothing wrong with Nginx.

It remains an excellent web server.

There are huge numbers of production applications running:

Nginx
+
PHP-FPM

successfully.

If my application is stable, monitored, performant and easy to operate, I don't see a good reason to change it merely because FrankenPHP is newer.

Newer is not automatically better.

When FrankenPHP becomes attractive

For me, I would investigate FrankenPHP when:

API traffic is high

or:

Application bootstrap is expensive

or:

We want worker mode

or:

We want a simpler PHP application server

or:

We want HTTP/2 / HTTP/3 and modern web-server features

or:

We are already using Docker and can test safely

Those are reasonable technical reasons.

When I would stay with PHP-FPM

I would probably stay with traditional PHP-FPM when:

Traffic is moderate

and:

The application performs well

and:

The team understands the current stack

and:

There is no measured performance bottleneck

and:

The hosting environment is already optimized

Changing infrastructure without a measurable reason is not optimization.

It is just change.

The memory problem deserves respect

This is one area where I would be particularly careful.

A long-running process can accumulate memory when application code is not designed correctly.

For example:

Request 1
↓
Memory increases

Request 2
↓
Memory increases again

Request 3
↓
Memory increases again

Eventually the worker becomes unhealthy.

That means monitoring memory usage becomes important.

You may also need periodic worker recycling.

This is why Laravel Octane provides settings such as maximum request counts for workers. The official FrankenPHP integration exposes options including worker count and --max-requests.

This is a good example of how performance optimization creates new operational responsibilities.

Singleton mistakes become more important

Suppose a service stores:

$this->currentUser

or:

$this->currentTenant

inside a long-lived object.

That can become dangerous.

The next request may reuse the same object.

Now we have a possible cross-request state problem.

This is especially important for SaaS applications.

Imagine:

Request 1
Tenant A

Request 2
Tenant B

If tenant-specific state accidentally remains in memory, that can become a serious security problem.

This is not just a performance issue.

It is also an isolation issue.

So Octane needs better engineering discipline

This is why I would summarize the difference like this:

PHP-FPM gives us a very strong isolation model naturally through the request lifecycle.

Long-running workers give us more performance opportunities.

But they require us to be more careful with state.

That trade-off is very important.

I would test before switching production

For an existing Laravel SaaS application, my approach would be:

First:

Baseline

Measure the current system.

Then:

FrankenPHP / Octane

Run the same application.

Then measure:

Requests/sec
Latency
CPU
Memory
Database load
Error rate
Worker stability

Then compare.

Not:

"Looks faster."

But actual numbers.

I would also test long-running behavior

This is one thing that normal benchmark tests may miss.

I would run:

10 requests
100 requests
1,000 requests
10,000 requests

and monitor:

Memory
CPU
Errors
Worker restarts
Response times

If memory continues increasing, that is something we need to understand before production.

This is particularly interesting for APIs

Traditional Laravel web pages may benefit.

But API-heavy applications can be especially interesting because they often have:

  • High request rates
  • Consistent routes
  • Repeated application bootstrap
  • JSON responses
  • Database queries
  • Redis
  • Authentication

That makes long-running application servers an interesting optimization area.

But again:

The workload decides.

PHP is evolving beyond the old deployment model

This is probably the biggest reason I wanted to write about this topic.

PHP is often described using an outdated picture:

PHP
+
Apache
+
Old websites

Modern PHP can look very different.

We can now have:

PHP
+
Laravel
+
Octane
+
FrankenPHP
+
Docker
+
Redis
+
Modern HTTP

That is a completely different architecture.

FrankenPHP itself describes its goal as a modern PHP application server, with worker mode, HTTP/2, HTTP/3, automatic HTTPS and other modern capabilities.

I don't think PHP is standing still

This is another lesson I take from this trend.

Developers sometimes talk about PHP as if the ecosystem stopped evolving years ago.

It hasn't.

PHP performance has improved.

Laravel continues to evolve.

Application servers are evolving.

Deployment models are evolving.

Modern infrastructure is becoming much more interesting.

The language is not the only thing that matters.

The runtime architecture around the language matters too.

My final view

I don't think PHP-FPM is dead.

I don't think everyone should switch to FrankenPHP tomorrow.

And I don't think Octane automatically makes every Laravel application faster.

But I do think the PHP ecosystem has reached an interesting point.

For years, we accepted:

Nginx
+
PHP-FPM
+
Request
+
Response

as the standard model.

Now we have alternatives that let PHP applications behave more like long-running modern services.

For me, that is worth learning.

Especially when building API-heavy Laravel applications and SaaS systems where performance really matters.

My approach would be simple:

Don't switch because it is trendy.

Measure your current application.

Understand where the bottleneck is.

Test FrankenPHP or another Octane server against your real workload.

And if the numbers show a real improvement without introducing unacceptable complexity, then use it.

Because good engineering is not about choosing the newest technology.

It is about knowing when the newer technology solves a real problem.