Selama lebih dari satu dekade, cara menjalankan PHP di server produksi hampir selalu sama. Sebuah web server seperti Nginx berdiri di depan, dan PHP-FPM mengeksekusi kode di belakangnya sebagai proses terpisah. Keduanya berbicara lewat FastCGI, protokol biner untuk menyerahkan permintaan dari web server ke penerjemah bahasa. Model ini stabil dan masih menjalankan sebagian besar situs PHP di dunia.
Namun model itu menyimpan biaya yang mudah terlewat. Setiap permintaan memulai aplikasi Anda dari nol: memuat autoloader, membangun ulang container service, membaca konfigurasi, lalu membuangnya begitu jawaban terkirim. Pada aplikasi kecil biaya itu tidak terasa. Pada framework modern yang berat saat boot, ia bisa menjadi bagian terbesar dari waktu tanggap.
FrankenPHP adalah jawaban yang menempuh jalan berbeda. Alih-alih memperbaiki komunikasi antara dua proses, ia menghapus batas di antara keduanya.
Apa Itu FrankenPHP?
FrankenPHP adalah server aplikasi PHP yang dibangun di atas Caddy, web server modern berbahasa Go. Nginx dan Apache menyerahkan eksekusi PHP ke proses lain; FrankenPHP menjalankannya di dalam prosesnya sendiri. Satu binary menggantikan tiga hal sekaligus: web server, manajer proses, dan penerjemah bahasa.
Namanya merujuk pada Frankenstein, dan pilihan itu cukup jujur. Tiga teknologi yang biasanya hidup terpisah — kode PHP, web server Caddy, dan runtime Go — dijahit menjadi satu makhluk.
Proyeknya dibuat Kévin Dunglas dari Les-Tilleuls.coop. Repositorinya dibuka Maret 2022 dan versi 1.0 dirilis 7 Desember 2023. Titik baliknya terjadi pada 15 Mei 2025, ketika kode sumbernya dipindahkan ke organisasi GitHub resmi PHP dan The PHP Foundation ikut merawatnya. Tata kelolanya tetap dipegang para maintainer aslinya. Per Agustus 2026, proyek ini berlisensi MIT, mengumpulkan lebih dari 11.300 bintang, dan berada di versi stabil 1.12.7.
Perpindahan repositori itu meninggalkan jejak yang sering membingungkan. Nama image Docker resminya masih
dunglas/frankenphp, mengikuti akun pembuatnya, sementara kode sumbernya kini diphp/frankenphp. Keduanya proyek yang sama.
Cara Kerja FrankenPHP: PHP yang Ditanam ke Dalam Proses Go
Kelebihan sekaligus batasan FrankenPHP bermula dari satu pertanyaan: bagaimana PHP dan Go bisa berada dalam satu proses. Jawabannya ada pada dua keputusan arsitektur.
Pertama, FrankenPHP menanam penerjemah PHP ke dalam program Go melalui CGO, jembatan yang memungkinkan kode Go memanggil pustaka C. PHP sendiri ditulis dalam bahasa C, sehingga dapat diperlakukan sebagai pustaka biasa. Di atas jembatan itu, FrankenPHP menuliskan implementasi SAPI (Server API) versinya sendiri, yaitu lapisan penghubung antara penerjemah PHP dan lingkungan yang memanggilnya. Jadi FrankenPHP bukan web server yang kebetulan bisa menjalankan PHP. Ia adalah SAPI PHP di dalam proses Go, sejajar dengan PHP-FPM atau mod_php, bukan dengan Nginx.
Konsekuensi langsungnya: tidak ada socket FastCGI, tidak ada layanan kedua yang harus dipantau, dan tidak ada perjalanan data antarproses untuk setiap permintaan.
Nginx dan PHP-FPM adalah dua proses terpisah yang disambung FastCGI; Caddy dan PHP menyatu dalam satu proses FrankenPHP.
Kedua, setiap eksekusi PHP berjalan di atas thread POSIX asli, bukan goroutine (unit konkurensi ringan bawaan Go). Ini keharusan, bukan pilihan gaya. Model ZTS (Zend Thread Safety) pada PHP mengikat keadaan penerjemah ke thread sistem operasi yang nyata. Karena itulah paket resminya dinamai php-zts, dan karena itu pula sebagian ekstensi PHP tidak akan pernah jalan di sini.
Classic Mode dan Worker Mode: Di Sinilah Angka Kecepatannya Ditentukan
FrankenPHP punya dua cara menjalankan aplikasi Anda. Selisih performa di antara keduanya jauh lebih besar daripada selisih antara FrankenPHP dan stack lama.
Classic mode aktif secara bawaan. Perilakunya sama seperti server PHP tradisional: setiap permintaan menjalankan skrip dari awal, lalu membersihkan semuanya. Jumlah thread-nya tetap sejak server menyala, setara pm = static pada PHP-FPM, dan bisa menambah sendiri saat ramai lewat max_threads, setara pm = dynamic. Di mode ini FrankenPHP menjadi pengganti langsung PHP-FPM atau Apache dengan mod_php.
Worker mode bekerja secara mendasar berbeda. Skrip Anda di-boot satu kali, lalu tinggal di memori dan melayani permintaan berulang kali lewat sebuah loop. Autoloader, container service, dan konfigurasi hanya dibangun sekali seumur hidup proses. Secara bawaan FrankenPHP menyalakan dua worker untuk setiap inti CPU.
Classic mode mengulang boot aplikasi di tiap permintaan; worker mode boot sekali lalu menahan aplikasi di memori.
Selisihnya terukur. Sylius, penerbit platform e-commerce dengan nama yang sama, menerbitkan benchmark yang membandingkan tiga konfigurasi pada mesin identik. Mesin ujinya Scaleway DEV1-S, 2 vCPU dan RAM 2 GB, dengan database terpisah. Aplikasinya Sylius Standard di atas PHP 8.3, diukur memakai wrk selama 30 detik pada 100 koneksi.
| Konfigurasi | Permintaan/detik | Latensi p50 |
|---|---|---|
| Nginx + PHP-FPM | 21,60 | 4,54 detik |
| FrankenPHP classic | 20,30 | 4,72 detik |
| FrankenPHP worker | 57,65 | 1,65 detik |
Worker mode melayani 2,67 kali lebih banyak permintaan dibanding Nginx + PHP-FPM, dan memangkas latensi p50 sebesar 63,7%. Pada 200 koneksi selisihnya melebar menjadi 2,95 kali.
Sebaliknya, classic mode justru 6,0% lebih lambat dari Nginx + PHP-FPM pada uji yang sama, dan 8,2% lebih lambat pada 200 koneksi. Memasang FrankenPHP tanpa menyalakan worker mode karena itu tidak mempercepat apa pun. Nilai classic mode ada pada kesederhanaan operasi, bukan kecepatan.
FrankenPHP vs Nginx + PHP-FPM: Apa yang Digantikan
Bagi Anda yang terbiasa menyetel php-fpm.conf dan blok server {}, dokumentasi resminya menyediakan pemetaan yang cukup rapi.
| Pada stack lama | Padanan di FrankenPHP |
|---|---|
| Nginx/Apache + PHP-FPM | Satu binary frankenphp |
Blok server {} Nginx | Blok situs di Caddyfile |
Pengaturan pool php-fpm.conf | Opsi global frankenphp |
php_value / php_admin_value | Direktif php_ini |
pm.max_children | num_threads |
pm = dynamic | max_threads auto |
Perbedaan paling kentara ada di berkas konfigurasinya. Blok Nginx berisi try_files, fastcgi_pass, dan sederet fastcgi_param menyusut jadi empat baris:
example.com {
root /var/www/app/public
php_server
}Direktif php_server menangani pengarahan berkas PHP, perilaku mirip try_files, sekaligus penyajian berkas statis.
Untuk menyetel kapasitas, gantikan hitungan pm.max_children dengan num_threads. Rumus keamanannya disebut langsung di dokumentasi: num_threads dikalikan memory_limit harus lebih kecil daripada memori yang tersedia. Pada VPS dengan RAM 4 GB dan memory_limit 256 MB, batas atasnya sekitar 14 thread. Angka 12 memberi ruang aman untuk sistem operasi dan database.
{
frankenphp {
num_threads 12
max_threads auto
php_ini memory_limit 256M
}
}Fitur yang Tidak Anda Dapat dari Stack Lama
Beberapa kemampuan FrankenPHP tidak punya padanan di Nginx + PHP-FPM. Sebagian warisan Caddy, sebagian lahir dari penyatuan proses tadi.
- HTTPS otomatis: sertifikat diminta, dipasang, dan diperpanjang sendiri tanpa satu baris konfigurasi. HTTP/2 dan HTTP/3 aktif mengikutinya.
- Early Hints: kode status HTTP 103 mengizinkan server mengirim daftar aset untuk diunduh lebih awal, sementara PHP masih mengerjakan query lambatnya. Dokumentasi resminya menyebut praktik ini dapat memperbaiki waktu muat hingga 30%.
- Kemampuan real-time: modul Mercure tertanam di dalamnya, sehingga pengiriman pembaruan ke browser lewat Server-Sent Events tidak butuh layanan tambahan.
- Hot reload: perubahan berkas langsung memperbarui tampilan di browser tanpa memuat ulang halaman, berguna selama pengembangan.
- Kompresi Zstandard: satu baris
encode zstd br gzipmenyalakan tiga algoritma kompresi sekaligus. - Aplikasi menjadi satu berkas mandiri: skrip
build-static.shmembungkus kode, aset, penerjemah PHP, dan Caddy jadi satu berkas yang bisa dieksekusi. Ekstensinya dideteksi otomatis daricomposer.json, dan hasilnya dapat dikirim ke server tanpa memasang PHP.
Early Hints dipanggil dari kode PHP biasa:
$aset = '</style.css>; rel=preload; as=style';
header("Link: $aset");
headers_send(103);
// query dan perhitungan lambat Anda di sini
echo '<link rel="stylesheet" href="style.css">';Memasang dan Menjalankan FrankenPHP
Jalur tercepat untuk mencoba adalah skrip resminya. Pada Linux dan macOS:
curl https://frankenphp.dev/install.sh | shPengguna Windows memakai PowerShell:
irm https://frankenphp.dev/install.ps1 | iexUntuk produksi tersedia paket apt, dnf, dan apk bernama frankenphp, yang bergantung pada paket PHP bertanda php-zts untuk versi 8.2 sampai 8.5. Binary mandirinya berisi PHP 8.5 beserta ekstensi populer, dan pada Linux ditautkan secara statis sehingga berjalan di distribusi mana pun tanpa dependensi.
Menjalankan FrankenPHP lewat Docker
Jalur Docker paling banyak dipakai karena tidak menyentuh sistem host sama sekali. Image resminya bernama dunglas/frankenphp:
docker run -v .:/app/public \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphpSetelah terpasang, frankenphp php-server menyajikan isi direktori saat ini, sementara frankenphp php-cli skrip.php menjalankan skrip baris perintah. Konfigurasi paling minimal hanya dua baris di berkas bernama Caddyfile:
localhost
php_serverFrankenPHP di Windows
FrankenPHP berjalan native di Windows, lengkap dengan worker mode dan hot reload. Arsip Windows-nya sudah berisi binary PHP resmi, dan servernya bisa didaftarkan sebagai Windows service lewat WinSW. Ini berbeda dari PHP-FPM, yang memang tidak punya jalur build untuk Windows.
FrankenPHP untuk Laravel, Symfony, dan WordPress
Integrasi worker mode resmi tersedia untuk tiga framework: Laravel, Symfony, dan Yii. Komunitas menambahkan kerangka untuk Drupal, Joomla, TYPO3, dan Magento 2.
Laravel dan Laravel Octane
Untuk Laravel, cara tersingkat adalah memasang proyek ke direktori /app pada image Docker resminya. Cara kedua, jalankan frankenphp run dengan Caddyfile yang menunjuk public/ sebagai akar situs:
localhost {
root public/
encode zstd br gzip
php_server {
try_files {path} index.php
}
}Untuk menyalakan worker mode, Laravel menyediakan Octane. Tiga perintah berikut sudah cukup:
composer require laravel/octane
php artisan octane:install --server=frankenphp
php artisan octane:frankenphpOctane di sini bukan mesin performanya, melainkan pembungkus yang mengatur siklus hidup aplikasi Laravel agar aman ditahan di memori. Mesinnya tetap worker mode FrankenPHP.
WordPress di atas FrankenPHP
WordPress juga berjalan apa adanya. Cukup jalankan frankenphp php-server dari direktori instalasinya, lalu lanjutkan pemasangan lewat browser. Namun WordPress belum memiliki integrasi worker mode resmi. Yang Anda dapatkan sebagian besar adalah kemudahan operasi — HTTPS otomatis, HTTP/3, dan kompresi Zstandard — bukan lompatan angka seperti pada Laravel atau Symfony.
Kekurangan dan Hal yang Perlu Anda Pertimbangkan
Lima hal berikut berasal dari dokumentasi resminya sendiri, dan sebagian baru terasa setelah aplikasi berjalan beberapa minggu.
Ekstensi imap, newrelic, dan pcov tidak jalan di FrankenPHP; imagick bentrok di Docker — akarnya model thread ZTS.
- Ada ekstensi PHP yang tidak akan pernah jalan:
imap,newrelic, danpcovtidak aman dipakai bersamaan oleh banyak thread. Sekali lagi, penyebabnya model ZTS tadi. Ekstensiimagickbisa dipasang, tetapi thread OpenMP di dalamnya bentrok dengan thread FrankenPHP dan berujung crash. Yang terdampak hanya image Docker dan Homebrew; paket resmi lain sudah mematikan OpenMP. - Worker mode menuntut kode yang bersih dari sisa keadaan: variabel
staticdan properti statis pada kelas mempertahankan nilainya antar permintaan, dan superglobal$_ENVtidak direset. Data pengunjung sebelumnya dapat terbawa ke pengunjung berikutnya. Kebocoran memori pun menumpuk karena prosesnya tidak pernah mati. Pengamanmax_requestsbisa me-restart thread berkala, tetapi statusnya masih eksperimental dan bawaannya tanpa batas. - Script Composer yang memanggil
@phpgagal: perintah semacam@php artisan package:discovertidak berjalan karena Composer tidak mengenali binary FrankenPHP, dan flag-dbelum didukung. Solusinya membuat skrip pembungkus di/usr/local/bin/php. - Varian musl menghilangkan sebagian perilaku glibc: binary statis penuh dan image Alpine memakai pustaka musl, dan di sana flag
GLOB_BRACEpadaglob()tidak tersedia. Untuk produksi, dokumentasinya menganjurkan varian GNU atau image berbasis Debian. - Tidak tersedia di shared hosting: FrankenPHP mengganti seluruh lapisan penyajian, sehingga membutuhkan akses root pada server. Panel seperti cPanel belum menyediakannya sebagai pilihan penanganan PHP.
Satu pengalaman lapangan layak diperhitungkan. Sebuah tim yang mencoba Octane dengan FrankenPHP mengukur waktu boot framework turun dari 15 ms menjadi 11 ms. Namun waktu permintaan mereka tidak berubah: tetap 434 ms dan 360 ms pada dua server berbeda. Sebagian besar waktu itu habis menunggu panggilan jaringan, bukan mengeksekusi PHP. Mereka akhirnya kembali ke PHP-FPM karena harus merawat systemd unit khusus dan binary yang dipatch sendiri.
Kapan FrankenPHP Layak Dipakai, Kapan Tidak
Keputusannya bisa dipersempit menjadi tiga situasi dengan batas yang cukup jelas.
Pakai worker mode jika sebagian besar waktu permintaan habis untuk mengeksekusi PHP, bukan menunggu jaringan. Ciri praktisnya: aplikasi Laravel, Symfony, atau Yii dengan waktu tanggap di bawah 200 ms yang sebagian besarnya boot framework dan render template. Di sinilah angka 2,67 kali itu nyata. Prasyaratnya, kode Anda bersih dari variabel statis yang menyimpan data per pengunjung.
Pakai classic mode hanya jika tujuannya menyederhanakan operasi. Satu binary menggantikan dua layanan, satu container menggantikan dua container, dan HTTPS tidak perlu diurus. Jangan mengharapkan kecepatan, karena angkanya sedikit di bawah Nginx + PHP-FPM.
Jangan berpindah jika salah satu dari tiga kondisi ini berlaku. Pertama, beban aplikasi didominasi panggilan ke API atau database lambat, sehingga penghematan boot framework tenggelam di dalamnya. Kedua, aplikasi bergantung pada ekstensi di daftar tidak kompatibel. Ketiga, situs Anda berjalan wajar di shared hosting tanpa masalah kapasitas.
Kalau memutuskan mencobanya, siapkan lingkungan yang memberi akses root. Sebuah VPS Indonesia dengan RAM minimal 2 GB sudah memadai untuk pengujian serius. Mulailah dari classic mode, lalu nyalakan worker mode setelah variabel statis di kode Anda selesai diperiksa.
Pertanyaan yang Sering Muncul
Bagaimana cara menonaktifkan HTTPS di FrankenPHP?
Setel variabel lingkungan SERVER_NAME ke http:// atau ke :80. FrankenPHP mewarisi HTTPS otomatis dari Caddy, dan menuliskan skema http:// secara eksplisit adalah cara resmi mematikannya. Langkah ini dipakai saat pengembangan, atau ketika sudah ada reverse proxy lain yang menangani sertifikat.
FrankenPHP vs Swoole, apa bedanya?
Keduanya menahan aplikasi di memori, tetapi titik masuknya berbeda. Swoole adalah ekstensi PHP berisi server HTTP dan runtime asinkron, sehingga prosesnya tetap Anda atur sendiri. FrankenPHP adalah server aplikasi lengkap yang sudah membawa web server beserta HTTPS otomatis. Swoole memberi kendali lebih dalam atas model konkurensi, FrankenPHP memberi lebih sedikit komponen untuk dirawat. Keduanya tersedia sebagai driver Laravel Octane.
Apakah FrankenPHP menggantikan Nginx sepenuhnya?
Untuk melayani aplikasi PHP, ya. Caddy di dalamnya sudah menangani berkas statis, TLS, kompresi, dan pengarahan permintaan. Nginx masih dipertahankan jika Anda butuh aturan reverse proxy yang rumit, atau satu titik masuk bersama untuk banyak aplikasi non-PHP.
Versi PHP berapa yang didukung FrankenPHP?
Paket resmi untuk apt, dnf, dan apk menyediakan PHP 8.2 sampai 8.5 dalam varian ZTS, sementara binary mandiri dan image Docker terbarunya membawa PHP 8.5. Karena variannya selalu ZTS, ekstensi yang Anda pasang juga harus berasal dari paket bertanda php-zts.
Apakah FrankenPHP bisa dipakai di shared hosting?
Tidak. Menjalankannya berarti mengganti web server pada level sistem, dan itu menuntut akses root yang tidak diberikan pada shared hosting. Pilihannya VPS, dedicated server, atau platform berbasis container.
Apakah FrankenPHP sudah aman untuk produksi?
Cukup aman untuk dipertimbangkan. Versi 1.0 dirilis Desember 2023, proyeknya resmi didukung The PHP Foundation sejak Mei 2025, dan versi stabilnya kini 1.12.7. Yang perlu dipastikan bukan kematangan proyeknya, melainkan kesiapan kode Anda untuk berjalan di worker mode.
Kesimpulan
FrankenPHP adalah server aplikasi PHP yang menyatukan web server, manajer proses, dan penerjemah bahasa dalam satu proses, lewat penanaman PHP ke dalam program Go. Nilainya terbelah menjadi dua, dan sebaiknya tidak dicampur saat mengambil keputusan. Classic mode memberi penyederhanaan operasi tanpa perbaikan kecepatan. Worker mode memberi lompatan sekitar 2,7 kali, dengan syarat kode Anda bersih dari sisa keadaan antar permintaan.
Jika ingin mencobanya, dua langkah ini layak dikerjakan lebih dulu. Pertama, telusuri kode Anda untuk mencari variabel static dan properti statis yang menyimpan data per pengunjung. Di situlah masalah worker mode hampir selalu bermula. Kedua, cocokkan ekstensi yang aplikasi Anda pakai dengan daftar yang tidak kompatibel.
Semoga artikel ini membantu.




