24. Long-Running (RoadRunner)
What is RoadRunner and how does it work?
MiddleAnswer: RoadRunner is a high-performance PHP application server, load-balancer, and process manager written in Go. It works as a persistent process that manages a pool of PHP workers. When a request comes in, RoadRunner passes it to an available PHP worker via a high-performance binary protocol (Goridge). The PHP worker stays alive after the request is finished, eliminating the overhead of re-initializing the PHP engine and your application framework (bootstrapping) for every request.
Detailed RoadRunner Guide

What is a PHP Worker in the context of RoadRunner?
MiddleAnswer: A PHP worker is a script that runs in a continuous loop. It uses the Spiral\RoadRunner\Worker class to wait for requests from the RoadRunner server, process them (often via PSR-7), and send back responses. Workers can communicate with the server via standard pipes (default), TCP, or Unix sockets. Since RoadRunner 2.0, any warnings or output to STDOUT are automatically forwarded to STDERR to prevent protocol corruption.
How does RoadRunner manage the Pool of workers?
MiddleAnswer: RoadRunner maintains a pool of PHP workers and can dynamically scale them. It uses a supervision strategy to restart workers based on various limits defined in .rr.yaml:
max_jobs: Number of requests a worker can handle before being retired.max_memory: Memory limit per worker.ttl: Maximum lifetime for a worker.idle_ttl: Maximum duration a worker can spend in idle mode. For local development,pool.debug = truecan be used to allocate a worker only when a request arrives, simplifying debugging.
What should a developer keep in mind when writing code for a long-running PHP environment?
MiddleAnswer:
- Memory Leaks: Any leaked memory will accumulate over time; use
supervisor.max_worker_memoryas a safeguard. - State Persistence: Static variables and global state persist between requests, which can lead to data leaks or unexpected behavior if not reset.
- Resource Management: Database connections and file handles should be re-validated or properly closed, as they might time out or stay open across many requests.
- Error Handling: Uncaught exceptions might crash the worker; they should be caught and reported back to RoadRunner via
$worker->error().
What is the Key-Value (KV) plugin in RoadRunner?
MiddleAnswer: The KV plugin provides a unified interface to interact with various storage backends for simple key-value storage. It offloads caching or state management from PHP to the Go server. Supported drivers include:
redis(distributed)memcached(distributed)boltdb(file-based)memory(fast, local to the RR instance)
How do Queues and Jobs work in RoadRunner?
MiddleAnswer: RoadRunner acts as a job consumer and manager, receiving jobs from various brokers and pushing them to PHP workers. This centralizes job management without needing separate CLI processes. Supported drivers/brokers include:
amqp,beanstalk,redis,sqs,nats,boltdb, andmemory.
How does RoadRunner handle HTTP requests and headers?
MiddleAnswer: RoadRunner's HTTP plugin acts as a fast web server that converts incoming requests into PSR-7 compatible objects for PHP workers. It supports Gzip compression, custom headers, and middleware at the Go level. It can also handle response streaming, allowing PHP to send large payloads to the client incrementally.
What is the Centrifuge plugin in RoadRunner?
SeniorAnswer: The Centrifuge plugin integrates RoadRunner with Centrifugo or its Go-based equivalent, enabling real-time messaging (WebSockets, SockJS) in PHP applications. RoadRunner handles thousands of persistent connections in Go, while the PHP workers only handle business logic and events.
What is the purpose of the Service plugin?
SeniorAnswer: The Service plugin allows RoadRunner to run and monitor any binary or script as a sub-process (sidecar). It ensures the process is always running, automatically restarting it if it fails. This is ideal for background tasks like consumers, metrics exporters, or proxy servers.
How does the Locks plugin work?
SeniorAnswer: The Locks plugin provides a distributed locking mechanism. It allows PHP workers to synchronize access to shared resources across multiple workers or even multiple RoadRunner instances using backends like Redis or local memory.
What are the best practices for running RoadRunner in Production?
SeniorAnswer:
- Process Supervision: Use
systemdorsupervisordto keep the main RoadRunner process running. - Worker Limits: Always set
max_jobsormax_memoryto prevent memory bloat. - Health Monitoring: Use the
statusplugin for health and readiness checks. - OS Configuration: Increase the number of allowed file descriptors (
ulimit -n). - Logs: Configure structured logging (JSON) for easier ingestion by log management tools.
What is Response Streaming and Health Checks in RoadRunner?
SeniorAnswer:
- Response Streaming: Allows PHP to stream data to the client incrementally, reducing memory usage for large file downloads or real-time data feeds.
- Health Checks: The
statusplugin provides/health(is the server alive?) and/ready(is there at least one free worker?) endpoints. These are essential for Kubernetes liveness/readiness probes or load balancer health checks.
How does RoadRunner integrate with Temporal?
SeniorAnswer: RoadRunner can serve as a worker for Temporal, an orchestration engine for complex, stateful, and long-running workflows. PHP developers can write workflow and activity logic in PHP, while RoadRunner handles the communication with the Temporal server via the Goridge protocol.