1. Project Overview & Quickstart (roadrunner-server/roadrunner)
File: README.md
RoadRunner is an open-source (MIT licensed) high-performance PHP application server, process manager written in Go and powered with plugins โค๏ธ.
It supports running as a service with the ability to extend its functionality on a per-project basis with plugins.
Features
RoadRunner features a range of plugins, including HTTP(S)/2/3 and fCGI servers that are compatible with PSR-7/PSR-17 standards. This is just one of its many capabilities. It serves as an effective alternative to the traditional Nginx+FPM setup, providing improved performance and more flexibility. Its extensive plugin options go far beyond just HTTP(S)/2/3 and fCGI servers, offering a broad range of functionalities:
- Queue drivers: RabbitMQ, Kafka, SQS, Beanstalk, NATS, In-Memory.
- KV drivers: Redis, Memcached, BoltDB, In-Memory.
- OpenTelemetry protocol support (
gRPC,http,jaeger). - Workflow engine via Temporal.
gRPCserver. For increased speed, theprotobufextension can be used.HTTP(S)/2/3andfCGIservers features automatic TLS management, 103 Early Hints support and middleware like: Static, Headers, gzip, prometheus (metrics), send (x-sendfile), OTEL, proxy_ip_parser, etc.- Embedded distribute lock plugin which manages access to shared resources.
- Metrics server (you might easily expose your own).
- WebSockets and Broadcast via Centrifugo server.
- Systemd-like services manager with auto-restarts, execution time limiter, etc.
- Production-ready.
- And more ๐
Join our discord server: [Link](https://discord.gg/TFeEmCs)
Installation
The easiest way to get the latest RoadRunner version is to use one of the pre-built release binaries, which are available for
OSX, Linux, FreeBSD, and Windows. Instructions for using these binaries are on the GitHub releases page.
Docker:
To get the roadrunner binary file you can use our docker image: ghcr.io/roadrunner-server/roadrunner:2025.X.X (more information about
image and tags can be found here).
FROM ghcr.io/roadrunner-server/roadrunner:2025.X.X AS roadrunner
FROM php:8.3-cli
COPY --from=roadrunner /usr/bin/rr /usr/local/bin/rr
# USE THE RRConfiguration located in the .rr.yaml file (full sample):
Installation via Composer
You can also install RoadRunner automatically using the command shipped with the composer package, run:
composer require spiral/roadrunner-cli
./vendor/bin/rr get-binaryServer binary will be available at the root of your project.
Note
PHP's extensions
php-curlandphp-zipare required to download RoadRunner automatically.
PHP's extensionsphp-socketsneed to be installed to run roadrunner.
Check withphp --modulesyour installed extensions.
Installation option for the Debian-derivatives (Ubuntu, Mint, MX, etc)
wget https://github.com/roadrunner-server/roadrunner/releases/download/v2025.X.X/roadrunner-2025.X.X-linux-amd64.deb
sudo dpkg -i roadrunner-2025.X.X-linux-amd64.debDownload the latest release via curl:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/roadrunner-server/roadrunner/master/download-latest.sh | shMacOS using [Homebrew](https://brew.sh/):
brew install roadrunnerWindows using [Chocolatey](https://community.chocolatey.org/):
choco install roadrunnerConfiguration can be located in .rr.yaml file (full sample):
version: '3'
rpc:
listen: tcp://127.0.0.1:6001
server:
command: "php worker.php"
http:
address: "0.0.0.0:8080"
logs:
level: errorRead more in Documentation.
Example Worker:
<?php
use Spiral\RoadRunner;
use Nyholm\Psr7;
include "vendor/autoload.php";
$worker = RoadRunner\Worker::create();
$psrFactory = new Psr7\Factory\Psr17Factory();
$worker = new RoadRunner\Http\PSR7Worker($worker, $psrFactory, $psrFactory, $psrFactory);
while ($req = $worker->waitRequest()) {
try {
$rsp = new Psr7\Response();
$rsp->getBody()->write('Hello world!');
$worker->respond($rsp);
} catch (\Throwable $e) {
$worker->getWorker()->error((string)$e);
}
}[!IMPORTANT]
If you see theEOFerror, check that you have installed the PHP packages from this step.
If this does not help, try to execute the commandphp worker.phpdirectly and check the output.
Available Plugins: [link](https://docs.roadrunner.dev)
Run:
To run application server:
$ ./rr serve -c .rr.yamlLicense:
The MIT License (MIT). Please see LICENSE for more information. Maintained
by Spiral Scout.
Contributors
Thanks to all the people who already contributed!
File: schemas/readme.md
Schemas
This directory contains public schemas for the most important parts of application.
Do not rename or remove this directory or any file or directory inside.
- You can validate existing config file using the following command from the project root.
docker run --rm -v "$(pwd):/src" -w "/src" node:22-alpine sh -c \
"cd schemas && npm install && node test.js"2. Official Technical Reference & Guides (roadrunner-server/roadrunner-docs)
File: README.md
NEW DOCS ARE HERE: [LINK](https://github.com/roadrunner-server/docs)
RoadRunner is an open-source (MIT licensed) high-performance PHP application server, load balancer, and process manager.
It supports running as a service with the ability to extend its functionality on a per-project basis.
Contributors
Thanks to all the people who already contributed!
File: docs/en/lab/dashboards/dashboards.md
RoadRunner Dashboards
Grafana's dashboards for the RR (including temporal) installations. More info about the available metrics is here: link
gRPC dashboard
This dashboard contains gRPC plugin metrics: link
HTTP dashboard
This dashboard contains http plugin metrics: link
JOBS dashboard
This dashboard contains jobs plugin metrics: link
Temporal dashboard
This dashboard contains temporal (RR part) plugin metrics.
Official repo with the temporal metrics available here: https://github.com/temporalio/dashboards
File: docs/en/lab/dashboards/grpc.md
/* Detailed source-code truncated for AI context efficiency. */File: docs/en/lab/dashboards/http.md
/* Detailed source-code truncated for AI context efficiency. */File: docs/en/lab/dashboards/jobs.md
/* Detailed source-code truncated for AI context efficiency. */File: docs/en/lab/dashboards/temporal.md
/* Detailed source-code truncated for AI context efficiency. */File: docs/en/lab/access-logs.md
Logging โ HTTP Access logs
RoadRunner has the HTTP access logs support, which provides detailed information about incoming HTTP requests and
responses.
Note
This feature is disabled by default, but it can be easily enabled by configuring the HTTP server.
Enabling HTTP Access Logs
To enable HTTP access logs in RoadRunner, you need to modify the configuration file of the HTTP server.
Here's an example configuration file:
version: "3"
http:
address: 127.0.0.1:8000
access_logs: true
# ...Once enabled, RoadRunner will log the following information for each incoming HTTP request:
method- HTTP method of the requestremote_addr- Remote address of the clientbytes_sent- Content length of the responsehttp_host- Host name of the serverrequest- Query string of the requesttime_local- Local time of the server in Common Log Formatrequest_length- Request body size including headers in bytes (content-len + size of all headers) in bytes. Max allowed headers
size for the RR is 1MB.request_time- Request processing time in seconds with a milliseconds' resolutionstatus- HTTP response statushttp_user_agent- HTTP user agent string of the clienthttp_referer- HTTP referer string of the client
File: docs/en/lab/applogger.md
Logging โ Application logger
The RoadRunner server has a useful app-logger plugin that allows users to send logs from their applications to the
RoadRunner server using an RPC interface. This plugin is enabled by default and does not require any additional
configurations. It can be used to observe all application and server logs in one place. This is especially useful when
debugging and monitoring applications.
Note
It will send raw messages to the RoadRunnerSTDERR
Configuration
The logs section in the RoadRunner configuration file allows you to configure logging behavior for their application.
rpc:
listen: tcp://127.0.0.1:6001
logs:
channels:
app:
level: infoWarning
To interact with the RoadRunner app-logger plugin, you will need to have the RPC defined in the rpc configuration
section. You can refer to the documentation page here to learn more about the configuration.
The level key is used to specify the logging level for this channel. This means that only log messages with a severity
level of info or higher will be sent to this channel.
Note
Read more about logging in the Logging โ Logger section.
PHP client
The RoadRunner app-logger plugin comes with a convenient PHP package that simplifies the process of integrating the
plugin with your PHP application.
Installation
To get started, you can install the package via Composer using the following command:
composer require roadrunner-php/app-loggerUsage
After the installation, you can create an instance of the RoadRunner\Logger\Logger class, which will allow you to use
the available class methods.
Here is an example:
use Spiral\Goridge\RPC\RPC;
use RoadRunner\Logger\Logger;
$rpc = RPC::create('tcp://127.0.0.1:6001');
$logger = new Logger($rpc);
$logger->info('Hello, RoadRunner!');
$logger->warning('Something might be wrong...');
$logger->error('Houston, we have a problem!');Note
You can refer to the documentation page here to learn more about creating the RPC connection.
Available methods
debug(string): void: Sends a debug log message to the servererror(string): void: Sends an error log message to the serverinfo(string): void: Sends an info log message to the serverwarning(string): void: Sends a warning log message to the serverlog(string): void: Sends a log message directly to theSTDERRof the server
API
RPC API
RoadRunner provides an RPC API, which allows you to manage app-logger in your applications using remote
procedure calls. The RPC API provides a set of methods that map to the available methods of
the RoadRunner\Logger\Loggerclass in PHP.
Note
All methods accept astring(which will be log message) as a first argument and aboolplaceholder for the second
arg.
Error
Method sends an error log message with the specified message to the RoadRunner server.
func (r *RPC) Error(in string, _ *bool) error {}Info
Method sends an info log message with the specified message to the RoadRunner server.
func (r *RPC) Info(in string, _ *bool) error {}Warning
Method sends a warning log message with the specified message to the RoadRunner server.
func (r *RPC) Warning(in string, _ *bool) error {}Debug
Method sends a debug log message with the specified message to the RoadRunner server.
func (r *RPC) Debug(in string, _ *bool) error {}Log
Method sends a log message with the specified message directly to the STDERR of the RoadRunner server.
func (r *RPC) Log(in string, _ *bool) error {}File: docs/en/lab/health.md
Observability โ Health and Readiness checks
The RoadRunner Status Plugin provides a healthcheck status for various plugins such
as http, grpc, temporal, jobs and centrifuge. This plugin provides an easy way to check the condition of the
workers and ensure that they are ready to serve requests.
Activation of the Status Plugin
To activate the health/readiness checks endpoint, include a status section in your configuration file.
Here is an example:
version: "3"
status:
address: 127.0.0.1:2114The above configuration sets the address to 127.0.0.1:2114. This is the address that the plugin will listen to. You
can change the address to any IP address and port number of your choice.
To access the health check, you need to use the following URL: http://127.0.0.1:2114/health?plugin=http. This URL will
return the health status of the http plugin.
Note
You can specify multiple plugins by separating them with a comma. For example, to check the health status of both the
http and grpc plugins, you can use the following URL: http://127.0.0.1:2114/health?plugin=http&plugin=grpc.
The health check endpoint will return HTTP 200 if there is at least one worker ready to serve requests. If there are
no workers ready to service requests, the endpoint will return HTTP 500. If there are any other errors, the endpoint
will also return HTTP 500.
The readiness check endpoint will return HTTP 200 if there is at least one worker ready to take the request (i.e., not
currently busy with another request). If there is no worker ready or all workers are busy, the endpoint will returnHTTP 500 status code (you can override this too).
Customizing the Not-Ready Status Code
By default, Status Plugin uses a 500 status code. However, you can replace this status code with a custom one.
To achieve this, utilize the unavailable_status_code option:
version: "3"
status:
address: 127.0.0.1:2114
unavailable_status_code: 501Jobs plugin pipelines check
In addition to checking the health status of the workers, you can also examine the pipelines in the Jobs plugin using
the following URL: http://127.0.0.1:2114/jobs
This URL will return the status of the pipelines in the Jobs plugin. The output will be in the following format:
plugin: jobs: pipeline: test-1 | priority: 13 | ready: true | queue: test-1 | active: 0 | delayed: 0 | reserved: 0 | driver: memory | error:Use cases
The health check endpoint serves the following purposes:
Kubernetes Readiness and Liveness Probes
In Kubernetes, you can use readiness and liveness probes to check the health of your application. It can be used as a
readiness or liveness probe to ensure that your application is ready to serve requests. You can configure Kubernetes to
check the health check endpoint and take appropriate action if the endpoint returns an error.
Read more here
AWS Target Group Health Checks
If you are using AWS Elastic Load Balancer, you can use it as a health check for your target group. You can configure
the target group to check the health check endpoint and take appropriate action if the endpoint returns an error.
Read more here
GCE Load Balancing Health Checks
If you are using Google Cloud Platform, you can use it as a health check for your load balancer. You can configure the
load balancer to check the health check endpoint and take appropriate action if the endpoint returns an error.
Read more here
File: docs/en/lab/logger.md
Logging โ Logger
Logger Plugin is responsible for collecting logs from server plugins and PHP application workers' STDERR and
displaying them in the RoadRunner STDERR/STDOUT. It comes with a variety of options that allow you to customize the
way your application logs are collected and displayed.
Configuration
Modes
logs:
mode: productionThere are three available modes:
production- This mode uses logger settings that are optimized for production usage.development- This mode is enabled by default and is designed for use during application development. In
development mode, DPanicLevel logs panic, console colors are used, and logs are written to standard error. Sampling
is disabled, and stack traces are automatically included on logs of WarnLevel and above.raw- This mode displays messages as raw output without any formatting. This mode is useful in production
environments where you need to parse logs programmatically.
Note
Useproductionmode in production environments. It is optimized for production usage.
Encoding
Logger supports two types of encoding, console and json. By default, console encoding is used, which outputs logs
in a friendly format. JSON encoding, on the other hand, returns messages in a JSON Structured logging format. This
format presents log messages as JSON objects with key-value pairs representing each log message field, making them more
machine-readable and easier to process programmatically. JSON encoding is also better suited for production usage.
logs:
encoding: consoleLevel
The level is used to specify the logging level. This means that only log messages with a severity level will be sent to
this channel. Available levels include panic, error, warn, info, and debug.
logs:
level: infoNote
The default level isdebug.
Output
By default, RoadRunner sends logs to STDERR. However, you can configure RoadRunner to send logs to STDOUT by using
the output key.
logs:
output: stdoutLine Endings
It allows configuring custom line endings for the logger. By default, the plugin uses \n as the line ending. Note that the \n is a forced default. This means that if the value is empty, RoadRunner will still use \n. So no empty line endings are allowed.
logs:
line_ending: "\r\n"Channels
In addition, you can configure each plugin log messages individually using the channels section. It allows you to
customize the logger settings for each plugin independently. You can disable logging for a particular plugin or change
its log mode and output destination.
version: "3"
logs:
encoding: console # default value
level: info
mode: none # disable server logging. Also `off` can be used.
channels:
http:
mode: production
output: http.logFile Logger
It is possible to redirect channels or the entire log output to a file. To use the file logger, you need to set
the file_logger_options.log_output option to the filename where you want to write the logs.
Entire log
logs:
mode: development
file_logger_options:
log_output: "test.log"
max_size: 10
max_age: 24
max_backups: 10
compress: trueChannel
You can also redirect a specific channel to a file. To do this, you need to specify the channel name in the channels
logs:
mode: development
level: debug
channels:
http:
file_logger_options:
log_output: "test.log"
max_size: 10
max_age: 24
max_backups: 10
compress: trueAvailable options
log_output: Filename is the file to write logs to in the same directory. It usesprocessname-lumberjack.loginos.TempDir()if empty.max_size: is the maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes.max_age: is the maximum number of days to retain old log files based on the timestamp encoded in their filename.
Note that a day is defined as 24 hours and may not exactly correspond to calendar days due to daylight savings, leap
seconds, etc. The default is not to remove old log files based on age.max_backups: is the maximum number of old log files to retain. The default is to retain all old log files (though
MaxAge may still cause them to get deleted.)compress: determines if the rotated log files should be compressed using gzip. The default is not to perform
compression.log_ending: line ending to use in the logger. Default is new line -\n.
ZapLogger
Feel free to register your own ZapLogger extensions.