Folk
High-performance PHP application server powered by Rust.
Folk replaces nginx + php-fpm with a single binary that handles HTTP, gRPC, background jobs, metrics, and managed processes β all with zero-copy communication between Rust and PHP.
π¬ News and discussion: Folk on Telegram
Features
- HTTP server β Built on hyper/axum, dispatches requests to PHP workers
- Background jobs β In-memory or Redis-backed queues with retry policies
- gRPC server β Native gRPC with reflection support
- Prometheus metrics β
/metricsand/healthendpoints out of the box - Process manager β Supervised background processes with restart policies
- Fork-after-warm workers β a master warms PHP once, then forks N worker processes (crash isolation, force-kill, per-worker memory recycling)
- Streaming responses β True chunked HTTP via
Folk::writeHead/write/end, SSE support - Plugin architecture β Only include what you need
Quick Start
1. Install the extension
See Installation for Docker setup and building from source.
2. Install the SDK
3. Create folk.toml
See Configuration for all available options and PHP API for available native functions.
4. Run
Your application is now serving HTTP on port 8080 with 4 worker processes.
Laravel
1. Install
Folk integrates with Laravel automatically via a service provider. HTTP routes, job dispatching, and gRPC handlers work out of the box. Between requests the adapter resets auth, database transactions, events, queue, temp uploads, the container's scoped instances, and Inertia's shared props (Octane-parity), so persistent workers don't leak state across requests.
2. Create folk.toml
[workers]
script = "vendor/folk/laravel/bin/folk-server"
count = 4
[http]
listen = "0.0.0.0:8080"
public_dir = "public" # serve built assets (Vite/Inertia) from disk; miss β Laravel
3. Run
Per-request state reset
Folk keeps the app booted across requests, so request-scoped state you mutate must be reset before the next request. The built-in resetters cover the framework; register your own for package/app state via config/folk.php:
// config/folk.php
'resetters' => [
App\Folk\MyStateResetter::class, // implements Folk\Sdk\Reset\ResettableInterface
],
Spiral
1. Install
Folk integrates with Spiral Framework 3.x. HTTP pipeline, job processing, gRPC, and Cycle ORM cleanup work out of the box.
2. Create folk.toml
3. Run
Symfony
1. Install
Folk integrates with Symfony 6.4/7.x/8.x. HTTP kernel, services resetter, and Doctrine ORM cleanup work out of the box.
2. Create folk.toml
3. Run
Yii 3
1. Install
Folk integrates with Yii 3 via its native PSR-15 pipeline. HTTP handling, state resetter, and Cycle ORM cleanup work out of the box.
2. Create folk.toml
3. Run
Performance
Benchmarks on Docker (2 CPU, 512MB, 4 workers):
| Server | Raw JSON (req/s) | Laravel /ping (req/s) |
|---|---|---|
| Folk | 53,000 | 3,700 |
| Swoole | 73,000 | β |
| RoadRunner | 17,000 | β |
| FrankenPHP | 3,900 | β |
See Benchmarks for methodology and full results.
Architecture
Folk uses a fork-after-warm model: a single-threaded master boots PHP + your framework once, then forks N worker processes (the master only supervises). The embedded Rust runtime lives in each worker:
- Rust runtime (tokio) runs in each worker, handling its I/O: HTTP, gRPC, job queues
- PHP worker (one per process) handles business logic β your Laravel/Symfony/plain PHP code; the in-process RustβPHP bridge is zero-copy (no sockets, no serialization)
- Master supervises: respawn on crash, force-kill on
exec_timeout, RSS recycle; the metrics scrape server runs here over a shared-memory segment
| Component | Role |
|---|---|
| Master (PID 1) | Warms PHP, forks + supervises workers; runs master-only plugins (metrics scrape) |
| Workers 1βN (processes) | Each: own tokio + PHP, serve requests on SO_REUSEPORT |
| HTTP Plugin | Accepts HTTP requests, dispatches to the worker's PHP |
| Jobs Plugin | In-memory or Redis job queues |
| gRPC Plugin | Native gRPC server with reflection |
| Metrics Plugin | Prometheus /metrics + /health |
| Process Plugin | Supervised background processes |
Contributing
Found a bug or have an idea? See Contributing for how to report issues and propose features.