dmitry_kv15 Oct 2025 19:42

Running Laravel Octane with Swoole on a production API server for 3 months. Setup: Laravel 11, PHP 8.2, 4-core VPS, MariaDB + Redis.

Issues that hit us in production:

1. Static singletons leaking between requests Auth state, config caches, and one custom registry class stored user-specific data as static properties. Next request in the same worker would see stale data. Fix: use Octane-aware request lifecycle hooks to reset state.

2. Uploaded file temp paths disappear FPM cleans temp files at the end of each request. Octane does not. If you move() an uploaded file in a job dispatched from the request, the temp file is already gone by the time the job runs. Fix: move the file synchronously inside the request before dispatching.

3. Long-polling endpoints block the worker A websocket-style polling endpoint with a sleep() loop blocked the Swoole worker for the entire duration. With 4 workers and 4 polling clients the server was effectively down. Fix: use Swoole coroutine sleep or move polling to a separate process.

4. Horizon not seeing worker restarts Octane restarts workers on deploy but Horizon supervisor processes are separate. After deploy, queue workers ran old code while HTTP workers ran new code. Fix: add php artisan horizon:restart to the deploy script alongside php artisan octane:restart.

5. Log rotation breaks file handle Daily log rotation replaces the log file but the Swoole worker still holds the old file descriptor open. New log lines go to the deleted file. Fix: use a syslog or stderr driver instead of single file, or send SIGUSR1 to Swoole to reopen file handles.

Replies (6)
alex_petrov15 Oct 2025 20:10

Static state in facades persists between requests. The auth() facade stores the authenticated user. If you use Auth::login() inside a request without logging out, the next request in the same worker may see that user. Octane flushes this between requests for scoped bindings but custom static state does not get flushed.

0
ivan_morozov15 Oct 2025 20:36

The sandbox mode (–sandbox) is useful during development: it clears the application state between requests like FPM does. Slower but catches state leaks.

0
petr_sys15 Oct 2025 22:34

Memory usage per worker grows over time even without obvious leaks. We restart workers every 500 requests (–max-requests=500) as a precaution. The overhead is minimal and it prevents any slow leaks from accumulating.

0
vova15 Oct 2025 22:41

Octane does not work well with packages that hook into the request lifecycle via global state. Debugbar, some logging packages, some auth packages. Check package compatibility before deploying.

0
dmitry_kv16 Oct 2025 00:24

The concurrency() helper for parallel coroutines is one of the best features. Running two DB queries concurrently in a request cuts latency in half for read-heavy endpoints.

0
katedev16 Oct 2025 01:38

File upload handling is different with Octane. The temporary file cleanup that PHP usually handles on request end does not happen automatically. You need to clean up temp files explicitly.

0
Write a reply
Markdown. ```php blocks are runnable.