Laravel Octane to największa zmiana wydajnościowa, jaką możesz wprowadzić bez przepisywania aplikacji: zamiast bootować framework przy każdym żądaniu (jak PHP-FPM), Octane uruchamia aplikację raz i obsługuje tysiące żądań przez długo żyjące workery. Efekt to typowo 2–4× wyższa przepustowość i niższe czasy odpowiedzi. Ale Octane zmienia model wykonania kodu — i bez zrozumienia pułapek potrafi wyciekać dane między użytkownikami. Ten poradnik pokazuje, kiedy Octane ma sens, jak go wdrożyć i jak nie dać się zaskoczyć.
Najważniejsze: Najważniejsze — Octane trzyma aplikację w pamięci między żądaniami, więc eliminuje koszt bootstrapu (typowe 30–80 ms na żądanie). Działa na FrankenPHP, Swoole albo RoadRunner. Największe pułapki: stan w singletonach i staticach (wycieki między żądaniami), pamięć o starym kodzie (restart po deployu) i brak wsparcia dla niektórych pakietów. Dla małych aplikacji z niskim ruchem — nie warto.
Jak działa Octane — bootstrap raz, żądania w pętli
W klasycznym modelu PHP-FPM każde żądanie HTTP to: start procesu (albo jego recykling), odczyt i kompilacja plików, bootstrap Laravela (kontener, providery, routing, konfiguracja), wykonanie akcji, sprzątanie. Bootstrap to typowo 30–80 ms — płacony przy każdym żądaniu, nawet jeśli akcja trwa 5 ms.
- Octane odwraca ten model: uruchamia N workerów, z których każdy bootuje aplikację raz, a potem w pętli przyjmuje żądania. Framework, kontener i konfiguracja są już załadowane — zostaje samo wykonanie akcji. Stąd zysk: przy prostych endpointach 2–4× więcej żądań na sekundę i niższe opóźnienia (p95 potrafi spaść o połowę).
composer require laravel/octane
php artisan octane:install
php artisan octane:start --workers=4 --max-requests=500
FrankenPHP, Swoole czy RoadRunner — wybór serwera aplikacji
| Serwer | Zalety | Wady | Kiedy wybrać |
|---|---|---|---|
| FrankenPHP | Jeden binarny plik, worker mode „wbudowany", HTTPS/HTTP2/3 z pudełka, prosty deploy | Młodszy projekt | Domyślny wybór dla nowych wdrożeń |
| Swoole | Najbardziej dojrzały, ogromne możliwości (korutyny, timery) | Rozszerzenie PECL do skompilowania, pułapki z rozszerzeniami | Duże, wymagające systemy; zespół gotowy utrzymywać rozszerzenie |
| RoadRunner | Proces Go poza PHP, stabilny, dobre wsparcie | Osobny binarny proces do utrzymania | Zespoły chcące izolacji serwera od PHP |
Od Laravela 11 FrankenPHP jest domyślnym rekomendowanym wyborem — instalacja to binarny plik, a worker mode nie wymaga rozszerzeń PHP. RoadRunner i Swoole pozostają w pełni wspierane.
Kiedy Octane ma sens — a kiedy nie
Ma sens, gdy:
- Ruch jest stały i wysoki (setki tysięcy żądań dziennie i więcej) — koszt bootstrapu był realnym narzutem.
- Infrastruktura jest ograniczona pionowo (chcesz więcej z tego samego serwera, zamiast dokładać kolejny).
- Aplikacja jest „czysta": brak stanu w singletonach, staticach i globalach; brak pakietów zależnych od cyklu życia żądania.
- Czas odpowiedzi API ma znaczenie (np. SLA p95 poniżej 100 ms).
Nie ma sensu, gdy:
- Ruch jest niski — 10 tysięcy żądań dziennie nie zauważy różnicy, a zyskasz nowy system do utrzymania.
- Aplikacja trzyma stan w singletonach, ma wycieki pamięci albo pakiety niekompatybilne z Octane.
- Zespół nie ma doświadczenia operacyjnego — Octane wymaga restartów przy deployu, monitoringu pamięci workerów i zrozumienia nowego modelu błędów.
Wskazówka: Zanim wdrożysz Octane na produkcji, zrób test na stagingu z k6: zmierz RPS i p95 przed oraz po, przy tym samym scenariuszu. Jeśli zysk jest poniżej 30%, problem prawdopodobnie leży gdzie indziej (baza, N+1, brak cache) — Octane to optymalizacja „ostatniej mili", nie zamiennik pracy nad zapytaniami.
- ## Pułapka numer jeden: stan między żądaniami
W PHP-FPM każdy request zaczyna ze „świeżym" PHP: statiki, singletony i globalne zmienne żyją jeden request. W Octane workery żyją godzinami — więc wszystko, co trzymasz w pamięci procesu, przetrwa do kolejnego żądania.
// ŹLE w Octane: singleton z danymi użytkownika
class CartService
{
private array $items = []; // przetrwa między żądaniami!
public function add(Product $product): void
{
$this->items[] = $product;
}
}
Jeśli CartService jest singletonem (a w Laravelu wiele serwisów jest), koszyk użytkownika A może wyciec do użytkownika B. Analogicznie: statyczne cache'e w modelach, config() modyfikowany w runtime (utrwala się!), zmienne trzymane w app()->instance().
Jak się chronić:
- Trzymaj stan w request-scoped komponentach, nie w singletonach — dane per żądanie nie mogą żyć dłużej niż żądanie.
- Nie modyfikuj konfiguracji w runtime (
config(['x' => ...])w Octane zostaje zmienione na stałe). - Testuj: po wdrożeniu na stagingu wykonaj serię żądań jako różni użytkownicy i sprawdź, czy dane się nie mieszają.
- Włącz
octane.max_requests(recykling workerów) — to bezpiecznik, nie rozwiązanie, ale ogranicza skutki wycieków.
Deploy z Octane — restart i pamięć o kodzie
Octane ma ten sam problem co workery kolejek: proces trzyma kod w pamięci. Po wdrożeniu musisz zrestartować workery, inaczej serwujesz stary kod.
php artisan octane:reload # płynny reload workerów (bez przerwy w działaniu)
php artisan octane:stop
php artisan octane:start --workers=4 --max-requests=500
W produkcji Octane uruchamiasz pod Supervisorem (albo systemd) — dokładnie tak, jak workery kolejek.
Kroki wdrożenia
php artisan octane:reloadna końcu skryptu deploy (poconfig:cacheitd.).- Supervisor pilnuje procesu
octane:start(restart po awarii). - Monitoring pamięci workerów —
max-requests(np. 500) recyklinguje workera po N żądaniach; przy wyciekach w pakietach ustaw niżej (100–200).
[program:laravel-octane]
command=php /var/www/app/artisan octane:start --server=frankenphp --workers=4 --max-requests=500
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
Konfiguracja Supervisora dla procesów długo żyjących to ten sam warsztat, co dla workerów kolejek — warto trzymać obie usługi w jednym standardzie.
Octane a reszta stosu — czego nie zastępuje
Octane usuwa koszt bootstrapu, ale nie naprawia
- wolnych zapytań i problemu N+1 — baza nadal jest najczęstszym wąskim gardłem,
- braku indeksów,
- operacji zewnętrznych w cyklu żądania (kolejki!),
- ciężkiego frontendu.
W praktyce kolejność wdrożenia wygląda tak: najpierw zapytania, indeksy i cache (Octane przyspieszy wtedy jeszcze bardziej, bo każdy request jest lżejszy), potem Octane jako mnożnik przepustowości. Pełną kolejność optymalizacji opisuję w optymalizacji wydajności aplikacji Laravel.
Uwaga: Niektóre pakiety nie są kompatybilne z Octane (globalny stan, zależność od
$_SERVERw runtime, własne rozszerzenia). Przed migracją sprawdź listę znanych problemów dla swoich zależności i przetestuj wszystkie krytyczne ścieżki aplikacji na stagingu pod obciążeniem — nie tylko „kliknij i działa".
Najczęściej zadawane pytania
Czy Laravel Octane wymaga zmian w kodzie aplikacji?
Zwykle nie — Octane uruchamia tę samą aplikację w innym modelu. Ale musisz zweryfikować miejsca trzymające stan: singletony z danymi per-request, modyfikacje config() w runtime, statiki w modelach i serwisach. To nie zmiana kodu per se, tylko audyt „czystości" stanu — bez niego ryzykujesz wycieki danych między użytkownikami.
Ile zyskam na wydajności z Octane?
Typowo 2–4× więcej żądań na sekundę i niższe opóźnienia (bootstrap 30–80 ms znika z każdego żądania). Realny zysk zależy od tego, ile czasu żądanie spędzało w bootstrapie względem reszty: dla prostych endpointów bywa ogromny, dla zapytań trwających 2 s — niewielki. Zmierz k6 przed i po.
FrankenPHP czy Swoole — co wybrać w 2026?
FrankenPHP jako domyślny wybór: prosty deploy (jeden binarny plik), worker mode bez rozszerzeń, wsparcie HTTP/2 i HTTP/3, rekomendowany przez Laravel od wersji 11. Swoole wybierz, gdy potrzebujesz jego zaawansowanych możliwości (korutyny, timery) i masz doświadczenie w utrzymaniu rozszerzenia PECL.
Czy Octane działa z kolejkami i Horizon?
Tak — Octane dotyczy warstwy HTTP; kolejki działają niezależnie (workery queue:work pod Supervisorem). Możesz nawet uruchomić Horizon w tym samym serwerze aplikacji, pamiętając o osobnych limitach pamięci. octane:reload nie restartuje workerów kolejek — pamiętaj o queue:restart w deployu.
Co się dzieje z plikami i sesjami przy Octane?
Sesje działają normalnie (driver cookie/Redis — trzymaj je poza procesem). Uwaga na lokalne pliki: zapis do storage/ w jednym workerze jest widoczny dla pozostałych (wspólny system plików), ale cache w pamięci procesu (statiki) — nie. Sesje w plikach na wielu workerach to proszenie się o problem; użyj Redisa.
Czy warto wdrażać Octane na hostingu współdzielonym?
Nie — Octane wymaga własnego procesu (worker mode), kontroli nad restartami i Supervisorem. To rozwiązanie dla VPS/dedykowanych serwerów albo kontenerów. Na hostingu współdzielonym zostaje standardowa optymalizacja: OPcache i PHP-FPM.
👉 Rozważasz Octane albo potrzebujesz więcej mocy z obecnego serwera? Zrobimy test na stagingu z pomiarem przed/po — opisz projekt przez formularz. Zobacz też utrzymanie techniczne i SLA.
📖 Zobacz również: optymalizacja wydajności aplikacji Laravel, OPcache i PHP-FPM dla Laravel, Supervisor i systemd dla kolejek oraz load testing i profilowanie.