High-Performance Servers
BEAR.Sunday applications can run on high-performance PHP servers that eliminate per-request bootstrap overhead. This guide covers three server options: Swoole, RoadRunner, and FrankenPHP.
Overview
In traditional PHP-FPM, each request bootstraps the entire application:
Request -> Boot Framework -> Route -> Execute -> Response -> Shutdown
Request -> Boot Framework -> Route -> Execute -> Response -> Shutdown
Request -> Boot Framework -> Route -> Execute -> Response -> Shutdown
With persistent worker mode, the application boots once:
Boot Framework (once)
|
Request -> Route -> Execute -> Response
Request -> Route -> Execute -> Response
Request -> Route -> Execute -> Response
This eliminates boot overhead, resulting in significantly lower latency and higher throughput.
BEAR.Sunday’s stateless resource design and immutable architecture are well-suited for persistent worker environments, enabling seamless transition to worker mode without global state issues.
Server Comparison
| Feature | Swoole | RoadRunner | FrankenPHP |
|---|---|---|---|
| Language | C + PHP | Go + PHP | Go + PHP |
| Worker Mode | Yes | Yes | Yes |
| HTTP/2 | Yes | Yes | Yes |
| HTTP/3 | No | No | Yes |
| WebSocket | Native | Native | Via Caddy |
| Coroutines | Yes | No | No |
| Hot Reload | Manual | Yes | Yes |
| Memory Limit | Shared | Per worker | Per worker |
Quick Start with Docker
The bear-sunday-servers repository provides ready-to-use Docker configurations for all three servers.
git clone https://github.com/bearsunday/bear-sunday-servers.git
cd bear-sunday-servers
# Swoole (port 8081)
cd swoole && docker compose up -d && curl http://localhost:8081/
# RoadRunner (port 8082)
cd roadrunner && docker compose up -d && curl http://localhost:8082/
# FrankenPHP (port 8080)
cd frankenphp && docker compose up -d && curl http://localhost:8080/
Swoole
Swoole is a coroutine-based PHP extension providing event-driven asynchronous I/O.
Features
- Event-Driven: Asynchronous I/O handling
- Coroutines: Concurrent request processing without threads
- Request Isolation: Coroutine-context request isolation
- High Performance: Eliminates per-request boot overhead
- Memory Efficient: Shared memory between workers
Install
Swoole Extension (ext-swoole ^6.1)
pecl install swoole
Or compile from source:
git clone https://github.com/swoole/swoole-src.git && \
cd swoole-src && \
phpize && \
./configure && \
make && make install
Add extension=swoole.so to your php.ini.
BEAR.Swoole Package
composer require bear/swoole
Bootstrap Script
Create bin/swoole.php:
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/autoload.php';
$bootstrap = dirname(__DIR__) . '/vendor/bear/swoole/bootstrap.php';
$context = getenv('BEAR_CONTEXT') ?: 'prod-hal-app';
$ip = getenv('SWOOLE_IP') ?: '0.0.0.0';
$port = (int) (getenv('SWOOLE_PORT') ?: 8080);
exit((require $bootstrap)(
$context,
'MyVendor\MyProject',
$ip,
$port
));
Run
php bin/swoole.php
Swoole http server is started at http://127.0.0.1:8080
Environment Variables
| Variable | Default | Description |
|---|---|---|
BEAR_CONTEXT |
prod-hal-app | BEAR.Sunday context |
SWOOLE_IP |
0.0.0.0 | Server bind address |
SWOOLE_PORT |
8080 | Server port |
Development Notes
Xdebug is not fully compatible with Swoole’s coroutines. For debugging:
- Use
var_dump()/error_log()for simple debugging - Or disable Swoole and use PHP’s built-in server with Xdebug
Swoole does not support automatic hot reload. Restart after code changes:
# With Docker
docker compose restart
# Without Docker
pkill -f swoole.php && php bin/swoole.php
Parallel Execution
Swoole server involves two independent concerns:
- Server: How to run the application (this page)
- Parallel Execution: How to execute embedded resources concurrently
With BEAR.Async, #[Embed] resources are automatically executed in parallel using Swoole coroutines. See Parallel Resource Execution for details.
RoadRunner
RoadRunner is a high-performance Go application server with PSR-7 PHP workers.
Features
- Go Application Server: High-performance process manager
- PSR-7 Workers: Standard HTTP message interface
- Built-in Metrics: Prometheus-compatible endpoint
- Hot Reload: Automatic worker restart on file changes
Install
RoadRunner Binary
Download from releases or use Docker.
PHP Dependencies
composer require spiral/roadrunner-http nyholm/psr7
Configuration
Create .rr.yaml (see the bin/worker.php example implementation):
version: "3"
server:
command: "php bin/worker.php"
relay: pipes
http:
address: "0.0.0.0:8082"
pool:
num_workers: 4
max_jobs: 1000
allocate_timeout: 60s
destroy_timeout: 60s
logs:
mode: production
level: info
output: stdout
status:
address: "0.0.0.0:2112"
Run
./rr serve -c .rr.yaml
Environment Variables
| Variable | Default | Description |
|---|---|---|
BEAR_CONTEXT |
prod-hal-app | BEAR.Sunday context |
MAX_REQUESTS |
1000 | Requests before worker restart |
Metrics
Prometheus metrics available at http://localhost:2112/metrics.
FrankenPHP
FrankenPHP is a modern PHP application server built on Caddy with worker mode support.
Features
- Worker Mode: Eliminates application boot cost per request
- HTTP/2 & HTTP/3: Automatic HTTPS with Caddy
- Production Ready: OPcache JIT, multi-stage builds
- Development Ready: Xdebug, hot reload
Install
FrankenPHP is typically used via Docker. For standalone installation, see FrankenPHP documentation.
Run with Docker
docker run -v $PWD:/app -p 8080:8080 dunglas/frankenphp
Environment Variables
| Variable | Default | Description |
|---|---|---|
BEAR_CONTEXT |
prod-hal-app | BEAR.Sunday context |
MAX_REQUESTS |
1000 | Requests before worker restart |
SERVER_NAME |
:8080 | Listen address |
FRANKENPHP_NUM_WORKERS |
4 | Number of worker processes |
Memory Management
- Workers automatically restart after
MAX_REQUESTSto prevent memory leaks gc_collect_cycles()runs after each request- Set
MAX_REQUESTS=0for unlimited requests (development only)
Production Deployment
For production deployments, each server directory in bear-sunday-servers includes:
Dockerfile- Optimized production builddocker-compose.prod.yml- Production configuration- Health check endpoints
- OPcache optimization
Example production deployment:
cd swoole # or roadrunner, frankenphp
docker compose -f docker-compose.prod.yml up -d
Related
- Parallel Resource Execution - Parallel execution of
#[Embed]resources with BEAR.Async