← Semua pembelajaran / Laravel Nol → Enterprise
Fase 8 · FrankenPHP & RoadRunner

FrankenPHP vs RoadRunner — mana untuk enterprise

Keduanya cepat, keduanya matang, dan keduanya didukung Octane secara resmi. Perbedaan sesungguhnya bukan pada angka benchmark, melainkan pada arsitektur — dan pada berapa banyak bagian yang harus kamu operasikan.

Sumber asli laravel.com Artikel Rangkuman ~9 menit baca

Intisari

  • FrankenPHP: satu proses berisi web server + PHP. Lebih sedikit bagian, TLS dan HTTP/3 bawaan, konkurensi berbasis utas.
  • RoadRunner: server Go + proses PHP terpisah. Isolasi lebih kuat, kendali pool lebih detail, ekosistem plugin luas.
  • Untuk aplikasi web Laravel biasa, FrankenPHP adalah default yang lebih sederhana.
  • Pilih RoadRunner kalau kamu butuh gRPC, Temporal, antrean terkelola server, atau ekstensi PHP yang tidak thread-safe.
  • Keputusan terbesar bukan di antara keduanya — melainkan apakah kamu siap untuk worker mode sama sekali.

Perbedaan arsitektur, dan akibatnya

FRANKENPHP
  satu proses
  ├── Caddy: TLS, HTTP/1.1, HTTP/2, HTTP/3, berkas statis, kompresi
  └── PHP tertanam (ZTS) — satu utas per permintaan

ROADRUNNER
  proses Go                          proses PHP terpisah
  ├── plugin http                ←→  worker #1
  ├── plugin jobs                ←→  worker #2
  ├── plugin metrics             ←→  worker #3
  └── …                              (dihubungkan lewat pipa)
AspekFrankenPHPRoadRunner
Satuan konkurensiUtas dalam satu prosesProses terpisah
Butuh PHP thread-safe (ZTS)YaTidak
Isolasi antar permintaanBaikLebih kuat — satu crash tidak menyentuh yang lain
Memori per unit konkurensiLebih kecilLebih besar (satu proses PHP penuh)
Web serverTermasuk (Caddy)Perlu di depannya untuk TLS & statis
TLS otomatisBawaanTidak
HTTP/3BawaanAda di plugin http
Kendali poolUtas, worker, kolam per ruteSangat detail — TTL, memori, antrean, alokator dinamis
Ekosistem pluginModul CaddyJobs, gRPC, Temporal, KV, Centrifuge
Berkas konfigurasiCaddyfile.rr.yaml
Biner mandiri berisi aplikasiYaTidak
Dukungan OctaneResmiResmi
Saran soal AlpineHindari (musl lambat untuk ZTS)Hindari (musl tidak sepenuhnya kompatibel)

Soal benchmark

Jangan memilih berdasarkan angka benchmark orang lain. Keduanya menghapus biaya bootstrap yang sama, dan setelah itu waktu permintaanmu didominasi query database serta panggilan jaringan — bagian yang identik di kedua runtime. Perbedaan throughput di antara keduanya pada aplikasi Laravel nyata biasanya jauh lebih kecil daripada perbedaan yang dihasilkan satu index yang hilang. Ukur dengan aplikasimu sendiri, dengan beban yang menyerupai lalu lintas aslimu.

Kapan FrankenPHP lebih tepat

SituasiKenapa
Aplikasi web Laravel biasaSatu proses, satu konfigurasi, lebih sedikit yang bisa rusak
Ingin mengganti Nginx + PHP-FPMBisa dipakai sebagai pengganti langsung, tanpa mengubah kode
Butuh TLS otomatis atau HTTP/3Bawaan, tanpa komponen tambahan
Kontainer dengan memori terbatasUtas lebih hemat daripada proses
Situs yang banyak melayani berkas statisFile server Caddy memang kuat
Ingin mendistribusikan aplikasi sebagai satu binerFitur yang tidak ada di tempat lain
Tim kecilPermukaan operasional paling sempit

Kapan RoadRunner lebih tepat

SituasiKenapa
Butuh gRPC atau TemporalPlugin kelas satu; tidak ada padanannya di FrankenPHP
Antrean dikelola server yang samaPlugin jobs — satu proses melayani HTTP dan antrean
Ada ekstensi PHP yang tidak thread-safeRoadRunner memakai proses, bukan utas
Butuh kendali pool yang sangat rinciexec_ttl, max_worker_memory, max_queue_size, alokator dinamis
Kode warisan yang rawan crashIsolasi proses membatasi kerusakan
Sudah ada Nginx atau ALB yang mengurus TLSWeb server bawaan jadi tidak memberi nilai tambah

Rekomendasi

Untuk aplikasi Laravel skala enterprise yang berupa aplikasi web — termasuk yang bertrafik tinggi — mulai dari FrankenPHP. Alasannya operasional, bukan performa: ia satu proses, satu berkas konfigurasi, dan satu hal yang perlu dipantau. Di lingkungan kontainer, setiap komponen tambahan adalah sesuatu yang harus dibangun, di-deploy, dipantau, dan diperbaiki pada pukul dua pagi. FrankenPHP memberi hasil yang setara dengan bagian bergerak yang paling sedikit.

Pindah ke RoadRunner ketika ada kebutuhan konkret yang menariknya — gRPC, Temporal, antrean yang dikelola server, atau ekstensi yang tidak thread-safe. Itu bukan pilihan kedua; itu pilihan yang tepat untuk masalah yang berbeda. Karena keduanya diakses lewat Octane, berpindah nanti berarti mengubah satu opsi, konfigurasi deployment, dan menjalankan ulang uji beban — bukan menulis ulang aplikasi.

Keputusan yang sebenarnya lebih besar

Sebelum memilih di antara keduanya, jawab dulu pertanyaan ini: apakah aplikasimu siap untuk worker mode? Ia menuntut sesuatu yang tidak dituntut PHP-FPM — kode yang tidak menyimpan state antar permintaan, dan disiplin untuk mempertahankannya seiring bertambahnya orang yang menyentuh kode itu.

PertanyaanKalau jawabannya "tidak"
Sudah tidak ada singleton yang menyimpan data permintaan?Perbaiki dulu — ini risiko kebocoran data
Semua paket pihak ketiga mendukung worker mode?Periksa satu per satu; yang tidak jelas, uji beban panjang
Ada pemantauan memori per kontainer?Pasang dulu — kebocoran harus terlihat
Pipeline deploy me-restart worker?Tambahkan; tanpa itu kode lama tetap jalan
Query dan index sudah beres?Kerjakan itu dulu. Dampaknya lebih besar dan risikonya nol

Urutan yang menghasilkan perbaikan terbesar per satuan risiko: (1) perbaiki N+1 dan index; (2) pasang cache HTTP dan CDN untuk halaman yang sama bagi semua orang; (3) php artisan optimize dan OPcache; (4) skalakan mendatar dengan menambah kontainer; (5) baru worker mode. Banyak aplikasi yang mengira butuh worker mode sebenarnya butuh langkah kedua — dan langkah kedua tidak menambah satu pun kelas bug baru.

Jalur adopsi yang aman

  1. Selesaikan langkah 1–4 di atas. Ukur, dan catat angkanya.
  2. Jalankan FrankenPHP dalam mode klasik sebagai pengganti Nginx + PHP-FPM. Tidak ada perubahan kode, dan kamu sudah mendapat HTTP/3 serta satu proses yang lebih sederhana.
  3. Bereskan daftar periksa state dari materi jebakan state.
  4. Nyalakan worker mode di staging, jalankan uji beban panjang, pantau memorinya.
  5. Rilis ke produksi untuk sebagian lalu lintas dulu, dengan alarm memori dan 5xx yang siap.
  6. Baru setelah stabil, setel num_threads, max_threads, dan sisanya.

Latihan: jalankan uji beban yang sama pada tiga konfigurasi — PHP-FPM, FrankenPHP mode klasik, dan FrankenPHP worker mode — dengan aplikasimu sendiri. Catat throughput, p95, dan pemakaian memori masing-masing. Tabel hasilnya adalah dasar keputusan yang jauh lebih baik daripada rekomendasi siapa pun, termasuk halaman ini.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.