A redirect balancer between several hosts.

1.0 2021-04-19 10:28 UTC

This package is not auto-updated.

Last update: 2022-05-09 15:54:54 UTC


CI Workflow Codecov


This is a load balancer that doesn't act as a load balancer.

It is a redirect balancer. Instead of forwarding traffic to a specific host/port, it returns a 302 response with a different location.

Typical usage is that your entrypoint is https://example.com/foo and you want to redirect your traffic to a pool made of https://01.example.com and https://02.example.com, by keeping path and query string intact.

It is built with PHP 8 on top of ReactPHP. Because it answers very short responses and runs within a loop, it can easily handle thousands of requests/s without blinking an eye.


Build is optional (you can simply run php bin/console serve) but will produce an optimized, single-file executable PHAR.

PHP 8, Composer and Box are globally required on your computer.

To build the application, run:


It will land in bin/302.


Live balancing (no persistence - for testing purposes or prototyping)

php bin/302 serve \
--host= \
--port=8080 \
--pick=random \ # or round-robin
example1.org \
example2.org \

HTTP/1.1 302 Found 
Location: http://example2.org/foo?bar=baz

Persisted storage (Redis)

# Expose the REDIS_DSN variable if necessary, default is:
export REDIS_DSN="redis://localhost:6379"
php bin/302 serve --host= --port=8080

App will run, but user agent will get 503 errors because the server pool is empty.

Add a server to the pool

php bin/302 server:add example1.org

This command can be run while 302 serve is running, no need to restart the app!

Remove a server from the pool

php bin/302 server:remove example1.org

This command can be run while 302 serve command is running, no need to restart the app!

List servers in the pool

php bin/302 server:list




Example Supervisor config

After building the app, you can easily create a supervisor recipe to load it on startup:

command=php /usr/local/bin/302 serve --host= --port=80%(process_num)02d
environment = APP_LOG_DIR=/var/log/302

With the above config, 302 will run on,, and

Round-robin will be shared across the instances (since they share the same Redis instance).

CORS / SSL termination

302 has no built-in CORS nor SSL termination, but this can be handled by any web server with reverse-proxy capabilities (Apache, Nginx, Caddy, ...).

Caddyfile example

If you're using Caddy, here's an example Caddyfile:

example.org {
    @get {
        method GET
    @options {
        method OPTIONS
    header Access-Control-Allow-Origin *
    header Access-Control-Allow-Redirect true
    respond @options 200
    reverse_proxy @get