Powered by
Using FrankenPHP Workers

Using FrankenPHP Workers

Boot your application once and keep it in memory. FrankenPHP will handle incoming requests in a few milliseconds.

# Starting Worker Scripts

# Docker

Set the value of the FRANKENPHP_CONFIG environment variable to worker /path/to/your/worker/script.php:

docker run \
    -e FRANKENPHP_CONFIG="worker /app/path/to/your/worker/script.php" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Standalone Binary

Use the --worker option of the php-server command to serve the content of the current directory using a worker:

./frankenphp php-server --worker /path/to/your/worker/script.php

If your PHP app is embeded in the binary, you can add a custom Caddyfile in the root directory of the app. It will be used automatically.

# Symfony Runtime

The worker mode of FrankenPHP is supported by the Symfony Runtime Component. To start any Symfony application in a worker, install the FrankenPHP package of PHP Runtime:

composer require runtime/frankenphp-symfony

Start your app server by defining the APP_RUNTIME environment variable to use the FrankenPHP Symfony Runtime:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php" \
    -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Laravel Octane

See the dedicated documentation.

# Custom Apps

The following example shows how to create your own worker script without relying on a third-party library:

<?php
// public/index.php

// Prevent worker script termination when a client connection is interrupted
ignore_user_abort(true);

// Boot your app
require __DIR__.'/vendor/autoload.php';

$myApp = new \App\Kernel();
$myApp->boot();

// Handler outside the loop for better performance (doing less work)
$handler = static function () use ($myApp) {
        // Called when a request is received,
        // superglobals, php://input and the like are reset
        echo $myApp->handle($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
};

for($nbRequests = 0, $running = true; isset($_SERVER['MAX_REQUESTS']) && ($nbRequests < ((int)$_SERVER['MAX_REQUESTS'])) && $running; ++$nbRequests) {
    $running = \frankenphp_handle_request($handler);

    // Do something after sending the HTTP response
    $myApp->terminate();

    // Call the garbage collector to reduce the chances of it being triggered in the middle of a page generation
    gc_collect_cycles();
}

// Cleanup
$myApp->shutdown();

Then, start your app and use the FRANKENPHP_CONFIG environment variable to configure your worker:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

By default, 2 workers per CPU are started. You can also configure the number of workers to start:

docker run \
    -e FRANKENPHP_CONFIG="worker ./public/index.php 42" \
    -v $PWD:/app \
    -p 80:80 -p 443:443 -p 443:443/udp \
    dunglas/frankenphp

# Restart the Worker After a Certain Number of Requests

As PHP was not originally designed for long-running processes, there are still many libraries and legacy codes that leak memory. A workaround to using this type of code in worker mode is to restart the worker script after processing a certain number of requests:

The previous worker snippet allows configuring a maximum number of request to handle by setting an environment variable named MAX_REQUESTS.

Edit this page