Choosing a PHP application server used to be simple: you ran PHP-FPM behind Nginx, or you used Apache with mod_php. That was it. Today, you have genuinely compelling alternatives -- FrankenPHP, RoadRunner, Swoole, and LiteSpeed -- each with different architectures, trade-offs, and deployment models.
This guide compares the major PHP application servers head-to-head, covering architecture, performance characteristics, and practical deployment considerations. Whether you're evaluating a PHP-FPM alternative or trying to decide between FrankenPHP and RoadRunner for a new project, you'll find the comparison you need here.
The Traditional Setup: PHP-FPM and Apache mod_php
Before comparing modern alternatives, it's worth understanding the baseline that most PHP applications still run on.
PHP-FPM with Nginx
PHP-FPM (FastCGI Process Manager) is the most widely deployed PHP runtime. Nginx handles HTTP requests and forwards PHP requests to a pool of FPM worker processes via the FastCGI protocol. Each request gets its own process, the script executes, and the process resets for the next request.
How it works:
Client → Nginx (static files, TLS, routing) → PHP-FPM (PHP execution) → Response
This shared-nothing architecture is PHP's defining characteristic. Every request starts with a clean slate -- no leaked state, no memory accumulation, no cross-request contamination. It's simple, predictable, and easy to debug.
Strengths:
- Battle-tested across millions of production sites
- Extensive documentation and community knowledge
- Simple process model with predictable memory usage
- Works with virtually every PHP application without modification
- Easy horizontal scaling by adding more FPM workers or servers
Limitations:
- Bootstrap overhead on every request (framework loading, config parsing, service container building)
- No native HTTP/2 or HTTP/3 support at the PHP layer
- No built-in WebSocket or long-lived connection support
- Each worker handles one request at a time
Apache mod_php
Apache with mod_php embeds the PHP interpreter directly into the Apache process. It's the oldest deployment model and still common in shared hosting environments.
While simpler to configure initially, mod_php ties the PHP lifecycle to Apache's process model. This means PHP runs even for static file requests, consuming more memory. For most production workloads, PHP-FPM with Nginx offers better resource efficiency and separation of concerns.
Best for: Shared hosting, legacy applications where changing the server stack isn't practical, and .htaccess-dependent workflows.
FrankenPHP: The Modern Contender
FrankenPHP is a modern PHP application server built on top of Caddy, written in Go. It embeds PHP directly into the web server, eliminating the Nginx-to-FPM handoff entirely.
How it works:
Client → FrankenPHP (Caddy + embedded PHP) → Response
FrankenPHP's worker mode keeps your PHP application loaded in memory between requests, eliminating the bootstrap overhead that slows down traditional PHP-FPM setups. This is where the performance gains come from -- your framework, service container, and configuration are loaded once, not on every request.
Key features:
- Native HTTP/2 and HTTP/3 support
- Automatic TLS via Caddy's built-in ACME support
- Worker mode for persistent application state
- Early Hints (103) support for faster page rendering
- Built-in Mercure hub for real-time capabilities
- Official Symfony and Laravel integration
Strengths:
- Significantly reduced request latency in worker mode (community benchmarks typically show 2-4x throughput improvement over PHP-FPM for framework-heavy applications)
- Single binary deployment -- no separate web server, no FPM configuration
- Modern protocol support out of the box
- Active development with growing community adoption
Considerations:
- Younger project with a smaller production track record than PHP-FPM
- Worker mode requires your application to be free of memory leaks and global state issues
- Debugging can be more complex due to the persistent process model
- Go dependency for building from source
FrankenPHP vs PHP-FPM
This is the comparison most teams are evaluating right now. Here's how they stack up:
| Aspect | PHP-FPM (with Nginx) | FrankenPHP |
|---|---|---|
| Architecture | Separate web server + process manager | Single integrated server |
| Request model | Process-per-request (shared-nothing) | Worker mode (persistent) or classic mode |
| Bootstrap overhead | Every request | Once (worker mode) |
| HTTP/2, HTTP/3 | Nginx handles HTTP/2; no HTTP/3 in standard setups | Native HTTP/2 and HTTP/3 |
| TLS management | Manual or certbot | Automatic via Caddy |
| WebSockets | Requires separate solution | Supported via Mercure |
| Configuration | nginx.conf + php-fpm.conf + pool configs | Single Caddyfile or CLI flags |
| Maturity | 15+ years in production | Active since 2022 |
| Community size | Massive | Growing rapidly |
| Deployment complexity | Moderate (multiple components) | Low (single binary) |
When to choose PHP-FPM: You're running a stable application with no performance bottlenecks at the PHP layer, your team knows the Nginx/FPM stack well, or you need the broadest possible compatibility (shared hosting, legacy apps, WordPress multisite at scale).
When to choose FrankenPHP: You're starting a new project, your application's response time is dominated by framework bootstrap, you want HTTP/3 and automatic TLS without extra tooling, or you're building real-time features.
RoadRunner: The Go-Powered Worker Server
RoadRunner is a high-performance PHP application server written in Go. Like FrankenPHP's worker mode, it keeps your PHP application loaded in memory, but RoadRunner has been doing this since 2018 and has a more mature plugin ecosystem.
How it works:
Client → RoadRunner (Go HTTP server) → PHP Workers (persistent) → Response
RoadRunner manages a pool of long-lived PHP worker processes. Each worker loads your application once and handles many requests sequentially. The Go layer handles HTTP, load balancing, and additional services.
Key features:
- Worker mode with persistent PHP processes
- Built-in job queue system (Kafka, AMQP, SQS, Beanstalk support)
- gRPC server support
- Key-value storage, service bus, and metrics
- Plugin architecture for extensibility
- Temporal workflow integration
Strengths:
- Mature worker implementation with years of production use
- Rich plugin ecosystem beyond just HTTP serving
- Strong gRPC support for microservice architectures
- Excellent Spiral Framework integration, good Laravel and Symfony support
Considerations:
- Requires
.rr.yamlconfiguration - Your application must handle persistent state carefully (same as FrankenPHP worker mode)
- Adds Go as a runtime dependency
- Less community buzz than FrankenPHP despite being more mature
Swoole: The Async PHP Runtime
Swoole takes a fundamentally different approach. Rather than bolting a persistent worker onto PHP's traditional execution model, Swoole extends PHP itself with an asynchronous, event-driven runtime -- similar to what Node.js provides for JavaScript.
How it works:
Client → Swoole HTTP Server (PHP extension) → Coroutine-based Workers → Response
Swoole runs as a PHP extension (PECL install) and provides its own HTTP server, WebSocket server, and coroutine-based concurrency. A single Swoole worker can handle thousands of concurrent connections using cooperative multitasking.
Key features:
- Coroutine-based async I/O (database queries, HTTP requests, file operations)
- Built-in HTTP, WebSocket, TCP, and UDP servers
- Connection pooling for databases and external services
- Process management and task workers
- Millisecond-precision timers
Strengths:
- Highest potential throughput for I/O-bound workloads
- True concurrency within a single worker process
- Built-in connection pooling eliminates per-request connection overhead
- Laravel Octane provides first-class Swoole integration
Considerations:
- Steepest learning curve of all options -- async programming requires rethinking how you write PHP
- Not all PHP libraries are coroutine-compatible (blocking I/O in a coroutine blocks the entire worker)
- Debugging async code is harder than synchronous PHP
- PECL extension installation can complicate deployment pipelines
- Smaller Western community (project originated in China)
FrankenPHP vs RoadRunner vs Swoole
This is the three-way comparison developers evaluating modern PHP servers need. All three eliminate bootstrap overhead and keep your application resident in memory, but they differ significantly in scope and complexity.
| Aspect | FrankenPHP | RoadRunner | Swoole |
|---|---|---|---|
| Language | Go (Caddy-based) | Go | C (PHP extension) |
| Concurrency model | Workers (one request at a time per worker) | Workers (one request at a time per worker) | Coroutines (many concurrent requests per worker) |
| Installation | Single binary or Docker | Composer + binary | PECL extension |
| HTTP/2, HTTP/3 | Both native | HTTP/2 supported | HTTP/2 supported |
| WebSockets | Via Mercure | Via plugin | Native |
| Job queues | No (use external) | Built-in (Kafka, AMQP, SQS) | Built-in task workers |
| gRPC | No | Yes | Yes |
| TLS | Automatic (Caddy) | Manual configuration | Manual configuration |
| Framework support | Symfony, Laravel | Spiral, Laravel, Symfony | Laravel Octane, Hyperf |
| Maturity | ~3 years | ~7 years | ~8 years |
| Best for | Simple deploys, HTTP/3, new projects | Microservices, job queues, gRPC | High-concurrency I/O-bound workloads |
Choose FrankenPHP if you want the simplest deployment model with modern protocol support and don't need built-in job queues or gRPC.
Choose RoadRunner if you need a mature worker server with an integrated job queue, gRPC support, or you're building microservices.
Choose Swoole if your application is heavily I/O-bound (many database queries, external API calls per request) and you're willing to invest in learning async PHP patterns.
LiteSpeed and OpenLiteSpeed
LiteSpeed is a commercial web server with a drop-in Apache replacement and a built-in PHP handler (LSAPI). OpenLiteSpeed is its open-source counterpart.
LiteSpeed is particularly dominant in WordPress and shared hosting environments, where it provides significant performance improvements over Apache without requiring application changes.
Key features:
- Drop-in Apache replacement (reads
.htaccessfiles) - LSAPI -- a persistent PHP handler faster than FastCGI
- Built-in page caching (LSCache) with WordPress plugin
- HTTP/2 and HTTP/3 (QUIC) support
- Anti-DDoS features and ModSecurity compatibility
Strengths:
- Easiest migration path from Apache -- swap the server binary, keep your configs
- LSCache provides dramatic performance improvements for WordPress (often 5-10x faster page loads)
- Mature commercial product with enterprise support options
- OpenLiteSpeed provides most benefits for free
- Strong adoption in cPanel/WHM hosting environments
Considerations:
- LiteSpeed Enterprise requires a commercial license
- OpenLiteSpeed has a smaller feature set than the commercial version
- Less flexible than Nginx for complex reverse proxy configurations
- Primarily beneficial for WordPress and CMS-heavy workloads
Best for: WordPress sites, shared hosting migrations from Apache, teams that need HTTP/3 with minimal configuration changes, and hosting providers managing many sites.
Comparison Summary
| Server | Type | Best For | Complexity | HTTP/3 | Worker Mode | Maturity |
|---|---|---|---|---|---|---|
| PHP-FPM + Nginx | Traditional | General PHP hosting | Low | Via Nginx config | No | Excellent |
| Apache mod_php | Traditional | Shared hosting, legacy apps | Low | No | No | Excellent |
| FrankenPHP | Modern worker | New projects, simple deploys | Low | Yes | Yes | Growing |
| RoadRunner | Modern worker | Microservices, job queues | Medium | No native HTTP/3 | Yes | Good |
| Swoole | Async runtime | High-concurrency I/O workloads | High | No native HTTP/3 | Coroutine-based | Good |
| LiteSpeed/OLS | Web server | WordPress, Apache migration | Low | Yes | LSAPI (persistent) | Excellent |
Why Modern PHP Servers Use Go Under the Hood
You'll notice that both FrankenPHP and RoadRunner are written in Go. This isn't coincidence -- Go's goroutine-based concurrency model is well-suited for managing pools of PHP worker processes, handling HTTP connections, and coordinating I/O. It provides the high-concurrency connection handling that PHP's process model lacks, while letting PHP do what it does best: execute application logic.
Swoole takes the alternative approach of extending PHP itself with async primitives via a C extension, which avoids the Go dependency but requires more changes to how you write PHP code.
For most teams, the implementation language of the server doesn't matter -- what matters is the operational model and whether your application is compatible with persistent workers.
Deploying PHP Application Servers with DeployHQ
Whichever PHP server you choose, DeployHQ handles the deployment pipeline. Here's how DeployHQ integrates with each server type.
PHP-FPM and LiteSpeed Deployments
These are traditional deployments where DeployHQ excels. Your deployment pipeline typically looks like:
# Build commands (run in DeployHQ's build pipeline)
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
# Post-deployment SSH command
sudo systemctl reload php8.5-fpm
DeployHQ's build pipelines run your Composer install and framework optimisation commands before uploading files. The zero-downtime deployment feature ensures your site stays live during the entire process -- old files serve requests until the new release is fully uploaded and symlinked.
FrankenPHP and RoadRunner Deployments
Worker-based servers need a graceful restart after deployment to pick up new code. Since workers keep your application in memory, simply uploading new files isn't enough -- you need to signal the server to reload.
# Post-deployment SSH command for FrankenPHP
sudo systemctl reload frankenphp
# Post-deployment SSH command for RoadRunner
./rr reset
Configure these as post-deployment commands in DeployHQ. The server gracefully finishes in-flight requests, then loads the new code.
Swoole Deployments
Swoole-based applications (including Laravel Octane with Swoole) follow a similar pattern to RoadRunner:
# Post-deployment SSH command
php artisan octane:reload
Key DeployHQ Features for PHP Deployments
- Build pipelines: Run
composer install, asset compilation, and framework optimisation commands before deployment - Zero-downtime deployments: Atomic symlink switching ensures your site never goes offline during deployment
- Post-deployment hooks: Restart PHP-FPM, reload FrankenPHP workers, or reset RoadRunner processes after code is deployed
- Rollback support: If a deployment causes issues, roll back to any previous release instantly
- Multi-environment support: Deploy to staging with one PHP server configuration and production with another
If you're deploying PHP applications and want to learn more about deployment strategies, see our guide on deploying PHP applications with DeployHQ.
How to Choose the Right PHP Server
The decision comes down to three factors: your application's performance profile, your team's operational expertise, and your willingness to modify application code.
Stay with PHP-FPM if:
- Your application performs well and you have no specific bottleneck at the PHP layer
- You're running WordPress, Drupal, or other CMS platforms
- You want the broadest compatibility and easiest hiring
Move to FrankenPHP if:
- Framework bootstrap time is your biggest performance bottleneck
- You want a simpler deployment (single binary, automatic TLS)
- You're starting a new Laravel or Symfony project
Move to RoadRunner if:
- You need built-in job queues, gRPC, or microservice infrastructure
- You want a mature worker server with years of production track record
- You're using Spiral Framework or building service-oriented architectures
Move to Swoole if:
- Your application makes many concurrent I/O calls per request
- You need true async capabilities (WebSockets, real-time features)
- Your team is comfortable with async programming patterns
Move to LiteSpeed if:
- You're running WordPress and want the fastest possible page loads
- You're migrating from Apache and need
.htaccesscompatibility - You need HTTP/3 with minimal configuration effort
Frequently Asked Questions
Is FrankenPHP production-ready?
Yes. FrankenPHP has been used in production by multiple organisations and has official integration with both Symfony and Laravel. That said, it's a younger project than PHP-FPM or RoadRunner, so thorough testing in your specific environment is recommended before migration.
Can I switch from PHP-FPM to FrankenPHP without changing my code?
For most applications, yes. FrankenPHP's classic mode works as a drop-in replacement. Worker mode requires ensuring your application handles persistent state correctly (no global variable leaks, proper service container resets). Laravel and Symfony both provide guidance for worker-mode compatibility.
What happened to OpenSwoole?
OpenSwoole was a fork of Swoole that operated independently for a period. The project has since reverted to the original Swoole name. If you see references to OpenSwoole in older articles, they're referring to the same technology now maintained as Swoole.
Do I need to learn Go to use FrankenPHP or RoadRunner?
No. Both servers are distributed as pre-built binaries or Docker images. You configure them via configuration files (Caddyfile for FrankenPHP, .rr.yaml for RoadRunner) and interact with them through CLI commands. Go knowledge is only needed if you want to build custom server plugins.
Which PHP server is fastest?
There's no single answer. For I/O-bound workloads with many database queries, Swoole's coroutine model typically achieves the highest throughput. For CPU-bound or framework-heavy workloads, FrankenPHP and RoadRunner's worker modes provide similar performance gains by eliminating bootstrap overhead. PHP-FPM with proper tuning (opcache, preloading) remains competitive for many real-world applications. Always benchmark with your actual application rather than relying on synthetic tests.
Can I use DeployHQ with any of these servers?
Yes. DeployHQ deploys your code via SSH regardless of which application server you use. The difference is in your post-deployment commands: systemctl reload php-fpm for PHP-FPM, systemctl reload frankenphp for FrankenPHP, ./rr reset for RoadRunner, or php artisan octane:reload for Swoole via Laravel Octane. Get started with DeployHQ free.
How does LiteSpeed compare to Nginx with PHP-FPM?
LiteSpeed's LSAPI handler is generally faster than FastCGI for PHP execution, and its built-in caching (LSCache) provides significant performance improvements -- especially for WordPress. Nginx with PHP-FPM offers more flexibility for complex configurations and reverse proxy setups. If you're running WordPress or migrating from Apache, LiteSpeed is worth evaluating. For custom PHP applications, the difference is less pronounced.
Looking for a reliable way to deploy your PHP applications? Try DeployHQ free -- set up build pipelines, zero-downtime deployments, and post-deployment hooks for any PHP server in minutes.