Skip to content

Laravel Octane

Laravel Octane boots your app once and serves many requests from memory. Falak supervises Octane for you, gives it a private port on every server, and switches the edge to it only after it answers. Deployments restart Octane while Caddy holds incoming requests, so users see a short latency spike instead of errors.

  • A Laravel site deployed with Falak. See Deploy Laravel.

  • laravel/octane installed in your app:

    Terminal window
    composer require laravel/octane
    php artisan octane:install --server=frankenphp

    Commit the result (for FrankenPHP this includes public/frankenphp-worker.php).

  • For Swoole: the swoole or openswoole PHP extension on your servers. For RoadRunner: the rr binary and spiral/roadrunner-http in your app. Falak installs neither.

Octane server API value Available on Default
FrankenPHP (worker mode) frankenphp FrankenPHP sites only Default on FrankenPHP
Swoole swoole PHP-FPM or FrankenPHP sites Default on PHP-FPM
RoadRunner roadrunner PHP-FPM or FrankenPHP sites
  1. Open the site’s Settings → Laravel.
  2. Turn on Octane and pick the server (FrankenPHP is preselected on FrankenPHP sites).
  3. Save. Falak allocates a port and starts Octane on every server of the site (once the site has a live release).
  4. The Processes block shows the routing state per server: starting, then listening once Octane answered. Only then does the edge proxy to it.

The site card and panel header show an Octane badge.

Through the API:

Terminal window
curl -X PUT https://falak.example.com/api/v1/sites/shop/laravel \
-H "Authorization: Bearer $FALAK_TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"octane": true, "octane_server": "frankenphp"}'
Response
{"data": {"scheduler": true, "horizon": false, "octane": true, "maintenance": false, "octane_server": "frankenphp", "octane_port": 8412}}

Port allocation. Falak picks the port, you cannot set it. The first candidate is 8000 + crc32(site id) % 1000; if that is taken on any of the site’s servers, it takes the next free one. A port is free when no other site uses it as an app port, Compose host port, Octane port, or Octane auxiliary port (port + 10000, used for FrankenPHP’s --admin-port or RoadRunner’s --rpc-port). The port is kept when you switch Octane off and on again, and re-checked when you add servers.

The program. Falak supervises <slug>.octane:

Supervised command (FrankenPHP)
php8.4 artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8412 --admin-port=18412

Routing. Until Octane answers, the site keeps being served the normal way (FrankenPHP php_server or PHP-FPM). A probe waits up to 60 seconds for any HTTP answer on 127.0.0.1:<port>. Once verified, the edge serves existing files under public/ directly (never *.php, dotfiles or directories) and proxies everything else to Octane, retrying the upstream for up to 30 seconds.

Deploys. Octane resolves the current symlink once at start, so a reload would keep serving the old release. After activation, Falak restarts Octane (the program’s environment carries the new FALAK_RELEASE_ID). The old process gets 10 seconds to stop; meanwhile Caddy holds requests until the new process listens. Restart processes in the UI (same release) sends octane:reload instead.

Switching off. The route turns draining: the edge serves the site directly again, and the Octane program stops once no applied edge configuration proxies to it (or after 10 minutes).

  • Falak installs neither Swoole nor RoadRunner. Until they work, the probe keeps the site served directly.
  • Octane’s FrankenPHP server binds :<port> on all interfaces (Octane has no bind option). The server firewall’s default-drop policy blocks it from outside.
  • Octane under FrankenPHP uses the PHP embedded in the FrankenPHP binary, not the site’s phpX.Y CLI version.
  • If a verified Octane process crashes later, it is not un-routed automatically: requests get a 502 after the 30-second retry window, and the Process keeps crashing alert fires.
Symptom Fix
State stays starting Check the site’s Logs for the octane program. Common causes: laravel/octane not installed, missing public/frankenphp-worker.php, missing Swoole extension.
State failed The probe got no answer in 60 seconds. Fix the error, then redeploy or restart processes.
Code changes not visible after deploy You changed the deploy script to skip $FALAK_RESTART_PROCS. Keep it.
Per-request state leaking between requests Octane keeps your app in memory. Follow the Octane guidelines for singletons and static state.