Laravel Octane (Worker Mode)
ePHPm ships persistent worker mode ([php] mode = "worker") and a native
Laravel Octane driver — boot the Laravel application once per worker thread,
then handle requests in a loop with zero per-request bootstrap. Octane’s own
listeners (FlushArrayCache, FlushAuthenticationState, DisconnectFromDatabases,
…) reset framework state between requests; ePHPm supervises the workers.
The driver ships as the Composer package ephpm/octane-driver
(github.com/ephpm/octane-driver),
built on the shared base package ephpm/worker
(github.com/ephpm/php-worker) which
provides the Ephpm\Worker\Envelope type and IDE stubs for the engine
primitives.
ePHPm’s PHP packages are distributed via their GitHub repositories (not
Packagist). Install them by adding each repo in the dependency tree as a
Composer vcs repository.
1. Install the driver
In your Laravel project, add every ePHPm repo in the tree to composer.json.
The driver depends on ephpm/worker, so both repos are listed — Composer
does not resolve a VCS dependency’s own VCS repositories transitively, so
each ePHPm package needs its own repositories entry:
// composer.json
{
"repositories": [
{ "type": "vcs", "url": "https://github.com/ephpm/octane-driver" },
{ "type": "vcs", "url": "https://github.com/ephpm/php-worker" }
],
"require": {
"ephpm/octane-driver": "^0.1"
}
}Both ephpm/octane-driver and its ephpm/worker dependency are tagged
v0.1.0, so ^0.1 resolves for each; each still needs its own repositories
entry because Composer does not resolve VCS repos transitively. Then:
composer require laravel/octane
composer updateThis installs the worker entrypoint at vendor/bin/ephpm-octane-worker.
(Worker scripts starting with a #!/usr/bin/env php shebang are handled — the
engine skips the shebang line, so Composer bin proxies work as worker_script.)
2. Configure ePHPm
# /etc/ephpm/ephpm.toml
[server]
listen = "0.0.0.0:8080"
document_root = "/var/www/myapp" # the PROJECT ROOT, not public/
[php]
mode = "worker"
worker_script = "vendor/bin/ephpm-octane-worker"worker_script must resolve to a file under document_root (config load
hard-errors otherwise) — that is why document_root points at the project
root: vendor/bin/… lives there.
Tell the worker where the Laravel application lives via the EPHPM_APP_BASE
environment variable:
export EPHPM_APP_BASE=/var/www/myapp3. Start ePHPm — not octane:start
ephpmphp artisan octane:start --server=ephpm is not supported. With Swoole or
RoadRunner, Octane’s CLI supervises the server processes; with ePHPm the roles
are inverted — ePHPm is the server and supervises the worker threads itself
(spawn, boot watchdog, recycling, crash recovery, graceful drain). You start
ephpm; it boots the workers.
Worker lifecycle & tuning
All knobs live under [php] — see the config reference
for the full table:
| Key | Default | What it does |
|---|---|---|
worker_count | 0 (cgroup-quota- or CPU-derived) | Persistent worker threads, each holding a booted Laravel app. Derives from the cgroup CPU quota when running under one (Linux), otherwise host parallelism clamped 2–32. |
worker_max_requests | 10000 | Recycle a worker after N requests — pure leak guard for the framework kernel. 0 = never. |
worker_backlog | 0 (= worker count) | Dispatch-queue depth; a full queue applies backpressure. |
worker_boot_timeout | 30 | Seconds to reach the first take_request(); expiry logs an error and increments ephpm_worker_boot_timeouts_total (the thread is not killed — it still becomes ready if the boot completes). |
worker_stream_threshold | 1048576 | Bodies at/above this (or chunked) stream into the worker instead of buffering. |
Notes:
[php] workers(the fpm-mode concurrency semaphore) is ignored in worker mode — startup logs a WARN if it is set.worker_populate_superglobalsstaysfalsefor Octane: the driver builds requests from the engine’sEnvelope, never from$_GET/$_POST.- A fatal error or an
exit()/die()mid-request never wedges the server: the request gets a response (synthesized from SAPI headers + captured output forexit(); a 500 for a fatal) and the worker is recycled with a fresh boot. - Worker mode is a whole-server switch and is not supported together with
[server] sites_dir(multi-tenant vhosting) — config load hard-errors.
Observability
Worker metrics (ephpm_worker_pool_size, ephpm_worker_busy,
ephpm_worker_recycles_total, boot duration/failures/timeouts, dispatch queue
depth) are documented in the metrics reference.
Not yet implemented
The following Octane features are planned — not yet implemented in the ePHPm driver:
Octane::table()backed byephpm-kv(use theephpm_kv_*functions or the Redis-compatible listener directly in the meantime)Octane::tick()/ interval callbacks (noon_tickengine primitive exists)Octane::concurrently()- Octane’s
--watchmode
See also
- Laravel guide — classic (fpm-mode) Laravel deployment
- Config reference —
[php]— authoritative worker knobs - PSR-15 worker adapter — shipped generic adapter (Slim, Mezzio, …)
- Symfony Runtime adapter — planned