FrankenPHP — pengantar
FrankenPHP bukan proxy di depan PHP — ia adalah web server Caddy dengan interpreter PHP di dalamnya. Konsekuensinya besar: tidak ada Nginx, tidak ada FPM, tidak ada soket di antara keduanya.
Intisari
- Dibangun di atas Caddy: HTTPS otomatis, HTTP/2 dan HTTP/3, kompresi, berkas statis — semuanya bawaan.
- PHP tertanam sebagai pustaka; permintaan ditangani sebagai utas, bukan proses terpisah.
- Bisa dipakai sebagai pengganti langsung PHP-FPM (mode klasik), atau dinyalakan ke worker mode.
- Bisa mengemas seluruh aplikasi jadi satu berkas biner yang bisa dijalankan tanpa PHP terpasang.
- Sejak 2025 ia menjadi proyek resmi di bawah organisasi PHP.
Perbedaan arsitektur
TUMPUKAN KLASIK
internet → Nginx (TLS, statis) → soket → PHP-FPM (proses per permintaan)
↑ dua proses, dua konfigurasi, satu soket di antaranya
FRANKENPHP
internet → FrankenPHP (TLS, statis, PHP)
↑ satu proses, satu konfigurasi
| Kemampuan | Nginx + PHP-FPM | FrankenPHP |
|---|---|---|
| TLS otomatis (Let's Encrypt) | Perlu Certbot | Bawaan |
| HTTP/2 | Ya | Ya |
| HTTP/3 (QUIC) | Perlu build khusus | Bawaan |
| Kompresi Brotli & Zstandard | Perlu modul | Bawaan |
| Berkas statis | Ya | Ya |
| Early hints (103) | Tidak | Bawaan |
| Jumlah proses yang dijaga | Dua | Satu |
| Model konkurensi | Proses | Utas |
Menjalankan pertama kali
# Docker: cukup pasang proyekmu di /app
docker run -p 80:80 -p 443:443 -p 443:443/udp -v $PWD:/app dunglas/frankenphp
# Biner mandiri, dari folder proyek
frankenphp run
frankenphp php-server --root public/
Caddyfile
{
frankenphp
}
portal.test {
root public/
encode zstd br gzip
php_server {
try_files {path} index.php
}
}
Blok pertama menyalakan modul FrankenPHP; blok kedua mendefinisikan satu situs. Nama domain di sana bukan
sekadar label — Caddy memakainya untuk meminta sertifikat TLS secara otomatis. Menuliskan :80
sebagai gantinya mematikan HTTPS, yang tepat kalau ada load balancer yang sudah menanganinya.
Dua mode
| Mode klasik | Worker mode | |
|---|---|---|
| Bootstrap aplikasi | Tiap permintaan | Sekali per utas worker |
| Perubahan kode aplikasi | Tidak perlu | Perlu kode yang bersih dari kebocoran state |
| Perlu restart saat deploy | Tidak | Ya |
| Kecepatan | Setara PHP-FPM | Jauh lebih cepat |
Ini keunggulan adopsi yang nyata. Kamu bisa mengganti Nginx + PHP-FPM dengan FrankenPHP mode klasik hari ini, tanpa mengubah satu baris kode aplikasi, dan langsung mendapat HTTPS otomatis, HTTP/3, dan satu proses yang lebih sederhana. Worker mode bisa dinyalakan belakangan sebagai langkah terpisah — dua perubahan besar tidak perlu dilakukan sekaligus.
Konkurensi berbasis utas
{
frankenphp {
num_threads 16 # utas yang selalu ada
max_threads 48 # batas atas saat lalu lintas melonjak
}
}
Karena satuannya utas dan bukan proses, jejak memorinya lebih kecil daripada jumlah proses FPM yang setara. Konsekuensinya: PHP harus dikompilasi dalam mode thread-safe (ZTS) — dan setiap ekstensi PHP yang kamu pakai juga harus aman terhadap utas. Ini poin yang perlu diperiksa kalau aplikasimu bergantung pada ekstensi yang tidak umum.
Fitur yang tidak ada di tempat lain
| Fitur | Gunanya |
|---|---|
| Biner mandiri | Kemas aplikasi + PHP + server jadi satu berkas yang bisa dijalankan |
| Mercure | Server-sent events untuk pembaruan real-time, tanpa layanan tambahan |
| Early hints | Kirim 103 supaya browser mulai mengunduh aset sebelum HTML siap |
| Kumpulan utas terpisah | Endpoint lambat tidak menghabiskan seluruh kapasitas |
| Ekosistem modul Caddy | Rate limiting, autentikasi, dan proxy tanpa lapisan tambahan |
Catatan tentang Alpine. Dokumentasi FrankenPHP secara eksplisit menyarankan menghindari musl di produksi: PHP diketahui lebih lambat saat ditautkan ke musl dibandingkan glibc, terutama dalam mode thread-safe yang dibutuhkan FrankenPHP — dan sebagian bug hanya muncul di musl. Pakai image berbasis Debian. Ini kebalikan dari kebiasaan "pilih Alpine supaya image kecil", dan penting untuk diketahui sebelum menulis Dockerfile di Fase 9.
Latihan: jalankan aplikasimu dengan docker run … dunglas/frankenphp dalam mode klasik,
tanpa mengubah satu baris kode. Pastikan halaman terbuka, lalu jalankan
curl -sI --http3 https://localhost/ dan lihat bahwa HTTP/3 memang aktif.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.