Belajar FrankenPHP - PHP Server & PHP Worker
Episode 4 of 25

Belajar FrankenPHP - PHP Server & PHP Worker

Memahami dua cara FrankenPHP mengeksekusi PHP: php_server mode classic yang menangani request per-request seperti PHP-FPM, versus mode worker yang mem-bootstrap aplikasi sekali dan menyimpannya di memori, termasuk konfigurasi FRANKENPHP_CONFIG dan worker_num.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 3 kalian berhasil menjalankan FrankenPHP dengan php_server, pertanyaan besar berikutnya muncul: kapan cukup mode classic, dan kapan harus beralih ke worker? Episode ini menjawabnya. Kita akan membandingkan php_server (classic) dengan mode worker secara langsung, memahami cara mengaktifkan worker di berbagai setup (Caddyfile, Docker, standalone binary), dan belajar mengatur jumlah worker.

Topik ini adalah titik percabangan paling penting dalam series ini. Pilihan classic vs worker menentukan arsitektur aplikasi kalian — dari cara menulis kode, mengelola session, sampai strategi deployment — jadi pastikan memahami betul trade-off-nya sebelum memutuskan.

Mode Classic: php_server Sebagai Drop-in PHP-FPM

Tanpa konfigurasi tambahan, FrankenPHP berjalan dalam mode classic: setiap request dijalankan di thread yang tersedia, aplikasi di-bootstrap dari nol, dan state tidak bertahan. Secara perilaku ini identik dengan PHP-FPM — dan itu kabar baik: semua aplikasi PHP bisa langsung berjalan tanpa perubahan kode.

Caddyfile - mode classic
localhost {
    root * public/
    php_server
}

php_server di balik layar melakukan tiga hal: mengeksekusi file .php, melayani file statis (file_server), dan menangani try_files (mencari index.php untuk request direktori). Ini setara dengan blok server{} Nginx yang lengkap dengan try_files $uri $uri/ /index.php.

Kelebihan Classic

  • Kompatibel 100% dengan kode apa pun, termasuk kode legacy.
  • Tanpa risiko state leak antar request.
  • Paling mudah didiagnosis karena perilakunya persis PHP-FPM.

Kekurangan Classic

  • Bootstrap ulang aplikasi per request — mahal untuk framework modern.
  • Performa hanya setara PHP-FPM, tidak lebih.

Mode Worker: Aplikasi Persisten di Memori

Mode worker mengubah segalanya: aplikasi di-bootstrap sekali saat worker dimulai, lalu melayani banyak request dari memori. Bootstrap — membaca autoload composer, meregistrasi service, koneksi database — tidak diulang.

Ada tiga cara mengaktifkan worker, tergantung setup kalian.

1. Caddyfile: Subdirective worker di php_server

Caddyfile - worker di php_server
localhost {
    root * public/
    php_server {
        worker index.php 4
    }
}

Argumen kedua (4) adalah jumlah worker — padanan worker_num. Jika dihilangkan, defaultnya 2x jumlah core CPU. Lokasi file worker relatif terhadap root.

Untuk kontrol lebih detail, gunakan bentuk blok:

Caddyfile - worker dengan opsi
{
    frankenphp {
        worker {
            file /app/public/index.php
            num 4
            env APP_ENV production
            watch /app/**/*.php
        }
    }
}
  • num — jumlah worker (default 2x core).
  • env — environment variable khusus worker.
  • watch — restart otomatis saat file berubah (berguna untuk development).
  • max_consecutive_failures — batas gagal beruntun sebelum worker dianggap unhealthy (default 6).

2. Docker: Environment Variable FRANKENPHP_CONFIG

Di image Docker, kalian tidak menulis Caddyfile penuh — cukup inject konfigurasi via env var:

Worker via FRANKENPHP_CONFIG
docker run \
  -e FRANKENPHP_CONFIG="worker /app/public/index.php 4" \
  -v $PWD:/app \
  -p 80:80 -p 443:443 -p 443:443/udp \
  dunglas/frankenphp

Argumen terakhir (4) lagi-lagi adalah jumlah worker. Atau lewat Dockerfile:

Dockerfile - aktifkan worker
FROM dunglas/frankenphp
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
COPY . /app

3. Standalone Binary: php-server --worker

Untuk development cepat tanpa Caddyfile:

Worker via CLI
frankenphp php-server --worker public/index.php

Bahkan bisa ditambah --watch untuk restart otomatis:

Worker dengan file watching
frankenphp php-server --worker public/index.php --watch="/app/**/*.php"

Tip

Semua jalur worker bermuara pada hal yang sama: FrankenPHP menjalankan skrip worker sebagai proses persisten dan menyisipkan panggilan frankenphp_handle_request() untuk setiap request. Kita bedah skrip worker itu sendiri di episode 5.

Classic vs Worker: Perbandingan Langsung

AspekClassic (php_server polos)Worker (worker index.php)
Bootstrap aplikasiPer requestSekali saat start
Perintah eksekusifrankenphp run + CaddyfileSama, dengan subdirective worker
Konfigurasi tambahanTidak adaworker_num, env, watch
Kompatibilitas kodeSemua kodeKode yang bebas state leak
PerformaSetara PHP-FPMHingga puluhan kali lebih cepat
RisikoRendahState persisten antar request

Contoh nyata: aplikasi Laravel classic butuh ~50–100ms untuk cold start per request. Di mode worker, bootstrap 100ms itu dibayar sekali, lalu setiap request hanya membayar waktu pemrosesan aktual — sering kali di bawah 10ms.

Kesalahan Umum (Common Pitfalls)

  • Worker path salah: path file worker relatif terhadap root pada php_server; gunakan path absolut untuk menghindari ambiguitas.
  • Menjalankan worker tanpa menulis skrip worker: file worker harus berisi loop frankenphp_handle_request(). Untuk framework modern, pakai integrasi resminya (Laravel Octane di episode 6, Symfony runtime di episode 7) — jangan menulis loop manual tanpa alasan.
  • Lupa jumlah worker: default 2x core biasanya bagus untuk memulai, tetapi terlalu banyak worker × memory_limit bisa menghabiskan RAM (ingat aturan episode 2).
  • Kode dengan static state: di mode worker, static $count di dalam fungsi bertahan antar request. Kode seperti ini akan memberikan perilaku yang tidak terduga.

Penutup

Pada episode 4 ini, kalian telah memahami dua mode eksekusi FrankenPHP dan cara mengaktifkannya.

Inti yang harus dibawa pulang:

  • Classic (php_server polos) = drop-in replacement PHP-FPM; aman untuk semua kode.
  • Worker = aplikasi persisten; jauh lebih cepat; butuh kode yang bebas state leak.
  • Tiga jalur aktivasi: subdirective worker, env var FRANKENPHP_CONFIG, atau flag --worker.
  • Jumlah worker (worker_num) default 2x core; atur sesuai memori dan beban.
  • watch memungkinkan hot restart untuk development.

Di episode 5 selanjutnya kita membedah Worker Mode lebih dalam: boot & request handling — menulis skrip worker manual dengan frankenphp_handle_request() dan frankenphp_foreach_request(), perilaku superglobal antar request, restart worker, dan manajemen crash. Sampai jumpa di episode 5!