📑 Daftar Isi
- Langkah 1: Baca Log Error Nginx — Jangan Asal Tebak
- Langkah 2: Periksa Status dan Log PHP-FPM
- Langkah 3: Cek Memory dan Jejak OOM Killer
- Langkah 4: Cek Kecocokan Socket dan Port Upstream
- Langkah 5: Tuning PHP-FPM Biar Gak Gampang Mati
- Tabel Troubleshooting 502 Bad Gateway
- Pro Tips dan Warning dari Pengalaman
- FAQ: Pertanyaan yang Sering Ditanyain
- Q: Kenapa website saya error 502 padahal uptime server lama dan terlihat normal?
- Q: Apa bedanya error 502 Bad Gateway dan 504 Gateway Timeout?
- Q: Setelah ubah config PHP-FPM, apakah saya perlu restart Nginx juga?
- Q: Error 502 muncul terus-terusan tiap beberapa jam, kenapa?
- Q: Bagaimana cara fix 502 di server yang pakai cPanel atau Plesk?
- Kesimpulan
Fix Nginx 502 Bad Gateway: Panduan Troubleshooting Lengkap Production Server
Pas 2019, aku masih NOC junior yang tiap denger HP bunyi pas tengah malem langsung lemes. Dan ada satu malam yang sampe sekarang masih aku inget detailnya. Malam minggu, lagi asik nonton, eh HP meledak. Client nelpon, suaranya kenceng banget, “Mas, website-ku error 502 terus! Udah sejam lebih, client-ku pada komplain!” Aku cuma bisa dengerin sambil ngumpetin panik. Waktu itu yang aku tau cuma tombol restart.
Ya, gak bohong. Malam itu, dan beberapa bulan setelahnya, solusi andalanku cuma restart nginx, restart php-fpm, doa dikit, terus tinggal. Kadang jalan, kadang gak. Dan kalau gak jalan, aku makin bingung karena gak tau harus liat ke mana. Sekarang, tujuh tahun kemudian, udah ratusan kasus 502 yang aku tangani — dan rasanya udah kayak ketemu musuh lama yang dulu bikin ngeri, sekarang cuma bikin senyum. Mau tau gak? 502 itu sebenarnya gak semenakutkan kelihatannya, asal kita tau cara membacanya. Nah, di artikel ini aku mau ceritain semuanya dari nol: apa artinya, kenapa muncul, dan langkah demi langkah biar sampeyan bisa fix sendiri tanpa harus panik di jam 3 pagi.
Oke, kita mulai dari teori singkatnya dulu biar gak buta arah. 502 Bad Gateway di Nginx itu ceritanya gini: Nginx kamu itu ibarat penjaga pintu di depan sebuah rumah makan. Pengunjung dateng, penjaga pintu terima, terus dia bilang ke dapur, “Ada tamu, siapin satu porsi!” Nah, kalau dapurnya gak ada yang jawab, atau jawabannya aneh-aneh, penjaga pintu gak punya pilihan selain balik ke pengunjung dengan wajah datar: “Maaf, 502 Bad Gateway.” Dalam istilah teknis, “dapur” ini kita sebut upstream. Bisa PHP-FPM, bisa Apache, bisa Node.js, bisa Gunicorn, apa aja backend yang dipanggil Nginx lewat fastcgi_pass, proxy_pass, atau upstream block. Buat kasus paling umum di hosting Indonesia — WordPress, PHP — upstream-nya hampir selalu PHP-FPM.
Nah, ini penting banget dicamkan: error 502 di production server itu bukan cuma “web error” yang bisa dianggap enteng. Dampaknya nyata, lho. E-commerce yang down sejam aja bisa rugi ratusan ribu sampe jutaan rupiah. SEO bisa kena karena Google gak suka lihat website sering error. Trust user menipis, apalagi kalau ini kejadian pas mereka lagi mau bayar di checkout. Dan yang paling sering aku rasain sendiri — client nelpon marah-marah, management ikut panik, terus semua mata natap tim NOC. Reputasi tim jadi taruhannya. Jadi kalau sampeyan handle server production, 502 ini bukan cuma masalah teknis — ini masalah bisnis dan kepercayaan yang bisa bikin nama tim jelek di mata client.
Terus, kenapa sih 502 itu susah di-troubleshoot? Karena penyebabnya banyak banget dan gak keliatan dari permukaan. Bisa jadi karena socket PHP-FPM yang gak ketemu gara-gara versi PHP beda antara config Nginx dan yang keinstall. Bisa karena proses PHP-FPM ditewasin OOM killer diam-diam pas tengah malem. Bisa juga karena upstream-nya kebanyakan request dan semua worker-nya kehabisan slot, sampe request yang masuk cuma ngetumpuk dan akhirnya ditolak. Nah, daripada nembak-nembak asal (percaya deh, aku pernah — gak efektif, malah buang waktu), kita harus jalan sistematis. Dan sistematis itu artinya satu kata: log. Nggih, log. Delapan puluh persen kasus 502 yang aku temuin, jawabannya udah kelihatan jelas di log kalau kita mau baca pelan-pelan.
Sebelum lanjut ke langkah-langkahnya, aku mau ingetin satu hal yang sering aku liat dilewatin orang: jangan panik dan jangan asal restart. Restart itu bukan langkah pertama, itu langkah terakhir setelah kita tau penyebabnya. Ibarat lampu check engine nyala di mobil, orang yang bener gak langsung bongkar mesin — dia baca dulu indikatornya, baru mutusin mau diapain. Nah, di server, log itu indikatornya. Jadi kita mulai dari sana, pelan-pelan, urut, dan gak usah takut.
Langkah 1: Baca Log Error Nginx — Jangan Asal Tebak
Langkah pertama untuk fix nginx 502 bad gateway adalah baca log error Nginx. Log ini ada di /var/log/nginx/error.log, atau kalau VPS kamu pakai package manager standar, biasanya di path yang sama. Kalau kamu pakai panel kayak Plesk atau cPanel, lokasinya bisa beda dikit, tapi kita bahas yang standar dulu. Mulai dengan ngecek bagian paling belakang (yang paling baru):
tail -n 50 /var/log/nginx/error.log
Catatan: Kalau kamu gak nemu error.log di situ, cek juga /var/log/nginx/error.log.1 atau log di lokasi custom sesuai config. Bisa juga cek file config-nya: grep error_log /etc/nginx/nginx.conf. Biar gak bingung nyari-nyari.
Nah, kalau misalnya kamu dapet baris-baris kayak gini — ini yang paling umum aku temuin di kasus 502 — perhatiin baik-baik:
2026/07/21 03:12:11 [error] 27111#27111: *8917 connect() failed (111: Connection refused) while connecting to upstream, client: 203.0.113.25, server: site-lama-client.com, request: "GET /index.php HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "site-lama-client.com"
2026/07/21 03:12:12 [error] 27111#27111: *8918 connect() failed (111: Connection refused) while connecting to upstream, client: 203.0.113.25, server: site-lama-client.com, request: "GET /index.php HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "site-lama-client.com"
2026/07/21 03:12:12 [error] 27111#27111: *8919 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.7, server: site-lama-client.com, request: "GET /wp-login.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "site-lama-client.com"
2026/07/21 03:12:13 [error] 27111#27111: *8920 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.7, server: site-lama-client.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "site-lama-client.com"
2026/07/21 03:12:13 [error] 27111#27111: *8921 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.7, server: site-lama-client.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock:", host: "site-lama-client.com"

Mari kita bedah log ini baris per baris, karena di sinilah seni baca log itu sebenernya:
- Waktu (2026/07/21 03:12:11): Ini jam kejadian. Penting banget buat cross-check sama cron job atau event lain yang jalan di jam yang sama. Kalau 502 selalu muncul jam 03.00 pagi terus-terusan, kemungkinan besar ada cron yang makan resource gede di jam segitu.
- [error] 27111#27111: Ini level error dan PID dari worker Nginx yang nyoba connect ke upstream. Berguna buat nyari proses yang bersangkutan di ps aux kalau perlu.
- *8917: Ini nomor koneksi (connection number) internal Nginx. Bisa dipakai buat nyari request yang sama di access log.
- connect() failed (111: Connection refused): Ini kalimat kuncinya! Artinya Nginx nyoba nyambung ke upstream, tapi gak ada yang nerima koneksi di ujung sana. Kalau upstream-nya unix socket, artinya socket-nya gak aktif — php-fpm mati atau belum start. Kalau upstream-nya TCP (misal 127.0.0.1:9000), artinya gak ada yang nge-listen di port itu.
- upstream: “fastcgi://unix:/run/php/php8.1-fpm.sock”: Ini ngasih tau kita upstream yang mana yang bermasalah. Di sini jelas: fastcgi ke socket php8.1-fpm. Ini petunjuk emas buat langkah berikutnya.
- server: site-lama-client.com dan host: site-lama-client.com: Domain yang kena. Catat ya, domain di sini udah aku samarin jadi fiktif biar client asli gak kelihatan.
Jadi dari log di atas, pola yang keliatan: tiap detik muncul error connect refused ke socket php8.1-fpm. Artinya PHP-FPM-nya down, bukan sekedar sibuk. Kalau cuma sibuk, errornya beda — biasanya connect() timed out atau “no live upstreams”. Nah, dari sini kita lanjut ke PHP-FPM-nya, tapi sebelum itu, kalau kamu mau belajar lebih dalam soal kebiasaan baca log yang bener, cek artikel Cara Membaca Log Server Production ya — itu ngebangun dasar yang gak bakal nyesel.
Langkah 2: Periksa Status dan Log PHP-FPM
Karena log Nginx ngasih tau kita upstream-nya PHP-FPM, sekarang kita cek PHP-FPM-nya. Pertama, cek status servicenya:
systemctl status php8.1-fpm --no-pager
Kalau hasilnya “inactive (dead)” atau malah error “Unit php8.1-fpm.service could not be found”, berarti PHP-FPM-nya mati atau emang versinya beda. Cek versi yang terpasang dulu:
ls /etc/php/
apt list --installed | grep php | grep fpm
Nah, kasus klasik yang sering banget aku temuin di lapangan: konfigurasi Nginx masih nunjuk ke socket php7.4-fpm, padahal PHP-nya udah di-upgrade ke php8.1. Jadinya socket gak ada, semua request gagal, 502 di mana-mana. Ini yang bikin gemes, karena udah jelas banget di log tapi orangnya gak baca. Lha wong di baris log-nya udah ketulis “unix:/run/php/php8.1-fpm.sock”, terus di config Nginx ternyata fastcgi_pass-nya masih php7.4. Lucu, tapi sering kejadian — terutama abis proses update PHP versi.
Selanjutnya, baca log PHP-FPM. Kalau prosesnya mati, log ini biasanya nyimpen alasan kenapa mati. Lognya biasanya ada di /var/log/php8.1-fpm.log:
tail -n 30 /var/log/php8.1-fpm.log
Nah, kalau kamu nemu baris-baris kayak gini, itu tandanya PHP-FPM kewalahan:
[21-Jul-2026 03:10:12] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
[21-Jul-2026 03:10:13] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
[21-Jul-2026 03:11:02] WARNING: [pool www] server reached pm.max_children setting (50), consider raising it
[21-Jul-2026 03:11:58] NOTICE: [pool www] child 27155 started
[21-Jul-2026 03:12:11] WARNING: [pool www] server reached pm.max_children setting (50), consider raising it
[21-Jul-2026 03:12:12] ERROR: [pool www] child 27122 exited with code 137 (SIGKILL) after 5487.182469 seconds from start
Baris yang paling penting di sini adalah baris terakhir: “child 27122 exited with code 137 (SIGKILL)”. Code 137 itu artinya prosesnya ditewasin paksa, dan ini hampir selalu karena OOM killer yang ngekill proses karena kehabisan memory. Di atasnya, warning “seems busy” dan “server reached pm.max_children” udah ngasih sinyal dari awal bahwa worker-nya kepenuhan. Jadi alurnya ketahuan: worker abis, memory mepet, OOM ngekill, php-fpm tumbang, nginx balikin 502. Nah, kalau udah ke sini, kita pindah ke langkah berikutnya — ngecek memory dan jejak OOM killer-nya.
Langkah 3: Cek Memory dan Jejak OOM Killer
OOM killer itu kayak petugas keamanan yang jaga ketat di gedung. Kalau gedung (RAM) penuh, dia bakal usir beberapa penghuni — dan seringkali yang diusir itu proses yang paling gede, termasuk PHP-FPM. Buat fix nginx 502 bad gateway yang penyebabnya OOM, kita perlu cek dua hal: sisa RAM dan jejak OOM di kernel log.
Cek dulu sisa RAM-nya:
free -h
Terus cek jejak OOM killer di kernel log. Di Ubuntu/Debian modern, bisa pakai dmesg:
dmesg -T | grep -i "oom\|killed process" | tail -n 20
Kalau dmesg kena restriction (di beberapa kernel perlu akses khusus), coba lewat journalctl:
journalctl -k -b | grep -i "oom\|killed process" | tail -n 20
Kalau ada baris kayak gini, konfirmasi lengkap — OOM killer yang bunuh PHP-FPM:
[Tue Jul 21 03:11:54 2026] php-fpm8.1 invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
[Tue Jul 21 03:11:54 2026] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,totalvm=4G
[Tue Jul 21 03:11:54 2026] Out of memory: Killed process 27122 (php-fpm8.1) total-vm:1024MB, anon-rss:921MB, file-rss:0MB, shmem-rss:0MB
Nah lho, di situ jelas: “Out of memory: Killed process 27122 (php-fpm8.1)”. Dan totalvm-nya 4G. Jadi mesin ini cuma punya 4GB RAM dan PHP-FPM lagi ngabisin hampir 1GB per worker. Kalau ada beberapa worker jalan barengan, yasudah, langsung habis semua. Dari sini kita tau dua hal: mesinnya kekecilan buat beban ini, ATAU konfigurasi PHP-FPM-nya terlalu rakus. Dua-duanya harus dikoreksi biar 502-nya gak balik lagi.
Terus, kita juga perlu liat apa aja yang lagi makan memory. Ini penting buat mastiin jangan-jangan yang makan bukan PHP-FPM doang, tapi MySQL atau aplikasi lain yang lebih rakus:
ps aux --sort=-%mem | head -n 20
Outputnya biasanya kayak gini (beberapa kolom aku samarin biar gak kelewat panjang):
USER PID %CPU %MEM VSZ RSS COMMAND
www-data 27122 2.0 24.3 1048576 921312 php-fpm: pool www
www-data 27140 1.5 22.1 923648 839492 php-fpm: pool www
www-data 27155 1.8 20.9 902144 793280 php-fpm: pool www
root 1284 0.3 12.4 812512 471040 mysqld
root 27001 0.1 4.2 402340 159992 nginx: worker process
Nah, kalau liat pola kayak gini — beberapa worker PHP-FPM masing-masing makan 700-900MB — itu indikasinya website-nya bocor memory (memory leak) atau konfigurasi pool-nya gak cocok sama kapasitas mesin. Ini nanti kita perbaiki di langkah 5 dengan tuning. Kalau kamu pengen tahu lebih jauh soal pola memory leak dan cara bedah proses yang makan resource, artikel Panduan Troubleshoot High Load VPS bakal ngebantu banget.
Langkah 4: Cek Kecocokan Socket dan Port Upstream
Buat fix nginx 502 bad gateway, langkah ini ngecek apakah yang diarahin Nginx (fastcgi_pass atau proxy_pass) beneran ada di server. Ini sering banget jadi biang keladi — apalagi habis update PHP atau habis pindahin config dari server lain. Cek dulu upstream yang dipakai Nginx di semua site config:
grep -r "fastcgi_pass\|proxy_pass" /etc/nginx/sites-enabled/
Terus cek di sisi PHP-FPM, dia nge-listen di mana:
grep -r "listen" /etc/php/8.1/fpm/pool.d/
Dan verifikasi socket-nya beneran ada, beserta permission-nya:
ls -la /run/php/
Yang perlu dicocokin satu-satu:
- Kalau Nginx pake
fastcgi_pass unix:/run/php/php8.1-fpm.sock;, maka PHP-FPM harus nge-listen dilisten = /run/php/php8.1-fpm.sock. Gak boleh beda versi, gak boleh beda path. - Socket file harus beneran ada di output
ls -la /run/php/. Kalau gak ada, PHP-FPM-nya belum jalan atau listen-nya bukan di situ. - Permission socket harus bisa diakses oleh user yang jalanin nginx worker. Biasanya nginx jalan sebagai www-data, dan socket biasanya srwxrwxrwx, jadi aman. Kalau permission-nya beda, nginx gak bisa nulis ke socket — 502 lagi.
- Kalau pakai TCP, misal
fastcgi_pass 127.0.0.1:9000;, pastikan PHP-FPM nge-listen di port yang sama dan gak ada firewall yang ngeblokir koneksi ke localhost.
Nih, contoh mismatch yang sering banget aku temuin di client:
$ grep -r "fastcgi_pass" /etc/nginx/sites-enabled/site-lama-client.com
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
$ ls /run/php/
php8.1-fpm.pid php8.1-fpm.sock
$ php -v
PHP 8.1.29 (cli) (built: ...)
Nah lho. Config Nginx masih nunjuk php7.4, tapi yang keinstall cuma php8.1. Socket-nya beda, jadilah 502. Fix-nya: samain dulu. Ganti di config Nginx jadi php8.1-fpm.sock. Di kasus ini, yang paling bener adalah update config Nginx-nya, bukan muter balik ke PHP lama. Kalau kamu gak hati-hati nyocokin versi PHP pas upgrade, kamu bisa kena masalah ini di semua situs sekaligus.
Langkah 5: Tuning PHP-FPM Biar Gak Gampang Mati
Nah, ini langkah inti-nya. Kalau penyebab 502-nya karena PHP-FPM kewalahan (max_children reached) atau kebantai OOM, kita harus tuning pool-nya. Dan sebelum ngutak-ngatik config, mesti backup dulu. Ini bukan formalitas, ini penyelamat kalau-kalau salah setting.
PERINGATAN KEAMANAN: Backup Sebelum Melanjutkan
Sebelum mengubah konfigurasi pool PHP-FPM dan merestart service, pastikan kamu sudah:
- Backup file konfigurasi yang akan diubah.
- Verifikasi backup berhasil (file beneran ada dan isinya bener).
- Konfirmasi server target dan nama service yang benar.
Restart service production tanpa backup bisa menyebabkan downtime yang lebih lama dan konfigurasi hilang. Jangan sampe nangis di tengah malem gara-gara lupa backup.
Backup dulu file pool config-nya:
cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/www.conf.bak
Verifikasi backup-nya ada:
ls -la /etc/php/8.1/fpm/pool.d/
Terus buka dengan nano atau vim:
nano /etc/php/8.1/fpm/pool.d/www.conf
Kita fokus ke bagian “Process Manager”. Ada tiga mode: static, dynamic, dan ondemand.
- static: Worker selalu di-spawn segitu, gak peduli sepi atau rame. Stabil tapi boros RAM — gak cocok buat VPS kecil.
- dynamic: Nambah-nambahin worker sesuai kebutuhan, dengan batas min dan max. Ini paling umum dipakai dan paling fleksibel.
- ondemand: Worker dibikin cuma pas ada request, dimatiin kalau nganggur. Hemat RAM, tapi ada overhead pas request pertama dateng.
Nah, rumus simpel buat nyari max_children yang aman:
max_children = (RAM total - RAM cadangan OS) / rata-rata ukuran proses PHP
Contoh: VPS 4GB, cadangan buat OS + MySQL + Nginx kita sisihin 1.5GB, berarti sisa 2.5GB buat PHP. Rata-rata proses PHP di mesin itu sekitar 100MB per worker (kita liat dari ps aux tadi). Jadi:
max_children = (4096 - 1536) / 100 = 25.6 → 25 worker
Mending dikasih buffer dikit, jangan pas-pasan, karena beban bisa naik sewaktu-waktu. Contoh config yang aman buat VPS 4GB:
pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 1000
Penjelasan singkat tiap baris:
pm.max_children: jumlah maksimal worker. Ini yang paling penting — kalau ini kepenuhan, request bakal antri lama lalu gagal jadi 502.pm.start_servers: jumlah worker pas service start.pm.min_spare_serversdanpm.max_spare_servers: batas worker nganggur yang dijaga. Jangan sampe max_spare kelewat gede, sayang RAM.pm.max_requests = 1000: worker di-restart setelah handle 1000 request. Ini ngebantu banget nangkal memory leak — tiap worker yang bocor gak bakal bocor selamanya, dia di-respawn duluan sebelum bocornya parah.
Setelah ubah config, kita cek dulu validitas config-nya tanpa restart dulu — ini versi PHP-FPM-nya “nginx -t”:
php-fpm8.1 -t
Kalau output-nya “test is successful”, baru restart. Kalau ada error, baca dulu dan perbaiki — jangan restart dulu:
systemctl restart php8.1-fpm
Terus verifikasi statusnya jalan dan gak langsung crash:
systemctl status php8.1-fpm --no-pager
Dan test request ke website-nya:
curl -I https://site-lama-client.com/
Kalau udah balik normal, output curl bakal kayak gini:
HTTP/2 200
server: nginx/1.24.0
date: Tue, 21 Jul 2026 03:20:11 GMT
content-type: text/html; charset=UTF-8
HTTP 200, beres. Tapi jangan buru-buru tutup ticket, karena akar masalahnya (kenapa memory sampe abis) harus dipantau dulu. Cek terus selama beberapa jam ke depan:
watch -n 5 free -h
Dan buat mastiin worker-nya gak balik kepenuhan:
watch -n 5 systemctl status php8.1-fpm --no-pager | grep -E "Active|Processes"
Kalau mau lebih nyaman, pasang monitoring biar bisa kelihatan grafiknya. Aku saranin baca juga artikel Monitoring Server dengan Netdata — gak perlu jadi pro untuk paham grafiknya.
Tabel Troubleshooting 502 Bad Gateway
Biar gampang, aku rangkum dalam tabel. Cocokin gejala yang kamu liat di log, terus liat solusi cepatnya:
| Gejala di Log | Penyebab Kemungkinan | Fix Cepat |
|---|---|---|
| connect() failed (111: Connection refused) ke unix socket | PHP-FPM mati / crash / belum start | Start service, cek OOM, tuning pool |
| connect() failed (111: Connection refused) ke TCP port | Backend gak nge-listen di port itu, atau firewall blokir | Cek ss/netstat, cek firewall, samain port |
| connect() failed (2: No such file or directory) ke socket | Socket gak ada / path beda versi PHP | Samain fastcgi_pass dengan listen di pool config |
| upstream timed out (110: Connection timed out) | Backend lambat banget responnya | Naikin fastcgi_read_timeout / proxy_read_timeout |
| server reached pm.max_children setting | Semua worker PHP kepenuhan | Naikin max_children atau optimasi query/kode |
| no live upstreams while connecting to upstream | Semua backend di upstream block dianggap mati | Cek health check backend, cek aplikasi backend |
| child exited with code 137 (SIGKILL) | OOM killer ngekill proses | Cek RAM, tambah swap, tuning pool, cari memory leak |
| upstream sent invalid header while reading | Backend ngirim respon yang gak valid | Cek log aplikasi backend, debug aplikasi |
Pro Tips dan Warning dari Pengalaman
Aku pengen share beberapa hal yang jarang dibahas di tutorial lain, murni dari pengalaman di lapangan. Ini yang bikin perbedaan antara yang langsung ketemu solusinya dan yang muter-muter berjam-jam.
1. Beda 502 sama 504 itu penting. 502 artinya upstream gak bisa dihubungi atau ngirim respon invalid. 504 artinya upstream ketemu tapi responnya kelamaan. Kalau yang kamu liat 504, masalahnya biasanya di timeout — bukan di socket atau koneksi. Ini sering ketuker, dan salah arah berarti buang waktu berjam-jam. Kalau mau bedah lebih dalam soal 504, aku udah nulis juga di Cara Fix Nginx 504 Gateway Timeout.
2. Kalau pakai proxy_pass dengan domain, hati-hati sama DNS. Nginx resolusi hostname-nya pas config di-load, bukan per request. Kalau backend kamu domain yang IP-nya bisa berubah, nginx bakal pegang IP lama terus — dan kalau IP itu mati, jadilah 502. Solusinya pakai resolver 127.0.0.53; (atau DNS server kamu) di dalam server block, atau arahin langsung ke IP/port.
3. Jangan lupain Cloudflare atau CDN. Kalau website kamu di belakang Cloudflare, 502 yang kelihatan di browser itu bisa jadi 502 dari origin server yang ditembus Cloudflare. Cek langsung ke origin (pakai host header atau akses IP-nya) biar tau masalahnya sebenarnya di mana. Jangan salahkan Nginx kalau ternyata masalahnya di upstream yang beda.
4. “502 muncul tiap beberapa jam” itu pola klasik. Pola periodik kayak gini hampir selalu nunjuk ke cron job yang berat di jam tertentu, atau memory leak yang numpuk pelan-pelan sampe abis. Cek crontab client-nya, dan kalau ada backup yang jalan jam 3 pagi, curigai itu duluan. Jangan cuma restart terus lanjut tidur.
5. pm.max_requests itu penyelamat diam-diam. Banyak memory leak di aplikasi PHP yang gak kelihatan karena tiap worker di-respawn duluan sama pm.max_requests. Jangan anggap remeh nilai kecil kayak 500-1000. Ini murah tapi efeknya gede banget buat stabilitas jangka panjang.
FAQ: Pertanyaan yang Sering Ditanyain
Q: Kenapa website saya error 502 padahal uptime server lama dan terlihat normal?
Karena 502 itu masalah di level aplikasi/upstream, bukan di level server secara keseluruhan. Server bisa aja nyala terus, tapi PHP-FPM-nya mati atau worker-nya abis tanpa terlihat dari luar. Cek systemctl status php8.1-fpm, cek log error Nginx, dan cek log PHP-FPM. Kadang jawabannya udah nunggu di situ, tinggal dibaca.
Q: Apa bedanya error 502 Bad Gateway dan 504 Gateway Timeout?
502 berarti Nginx gak bisa dapet respon yang valid dari upstream — entah koneksinya ditolak, socket-nya gak ada, atau responnya rusak. 504 berarti upstream-nya ada dan kebuka, tapi gak ngirim respon dalam waktu yang ditentukan (biasanya 60 detik default). Kalau 504, kamu naikin fastcgi_read_timeout atau proxy_read_timeout. Kalau 502, mulai dari koneksi dan socket-nya.
Q: Setelah ubah config PHP-FPM, apakah saya perlu restart Nginx juga?
Gak wajib. Kalau kamu cuma ubah konfigurasi pool PHP-FPM (www.conf), cukup restart PHP-FPM doang. Tapi kalau kamu ubah konfigurasi Nginx (fastcgi_pass, server block, dll), baru perlu reload nginx. Karena kamu lagi ngehandle 502 yang melibatkan dua service, praktisnya: ubah semua config dulu, baru restart — PHP-FPM duluan, terus nginx reload. Biar gak dobel downtime.
Q: Error 502 muncul terus-terusan tiap beberapa jam, kenapa?
Pola periodik kayak gini biasanya nunjuk ke dua hal: cron job berat di jam tertentu yang makan memory sampe OOM, atau memory leak di aplikasi yang numpuk pelan-pelan. Cek dmesg buat jejak OOM killer, cek crontab, dan pasang pm.max_requests biar worker gak numpuk memory selamanya. Pantau resource dengan Netdata biar kelihatan pola-nya, jangan tebak-tebakan.
Q: Bagaimana cara fix 502 di server yang pakai cPanel atau Plesk?
Di panel, PHP-FPM biasanya dikelola otomatis, jadi langkahnya dikit beda. Mulai dari cek PHP version selector (di cPanel namanya MultiPHP) — pastikan versi yang dipilih konsisten sama yang dipake Nginx. Cek error log lewat interface atau terminal, dan kalau perlu restart service lewat WHM “Restart Services”. Prinsipnya sama: cari log-nya dulu, baru ketahuan arahnya ke mana.
Kesimpulan
Nah, gitu ceritanya. Nek aku balikin ke malam minggu 2019 itu — sekarang kalau ada client nelpon soal 502, aku gak panik lagi. Cukup jalanin alur yang sama: baca log Nginx, temuin upstream-nya, cek status PHP-FPM, cek memory dan OOM, samain socket, tuning pool, selesai. Biasanya di langkah 2 atau 3 jawabannya udah keliatan, sisanya tinggal konfirmasi.
Kalau kamu mau belajar lebih dalam soal baca log, cek juga artikel Cara Membaca Log Server Production dan Panduan Troubleshoot High Load VPS. Dua-duanya bakal ngebantu banget buat kasus kayak gini. Dan kalau RAM VPS-mu emang pas-pasan, baca Optimasi PHP-FPM untuk VPS RAM Kecil — itu resep jitu buat mesin kecil yang gampang kepenuhan. Referensi resmi buat modul fastcgi juga bisa dibaca di dokumentasi Nginx kalau mau dalem.
Pernah ngalamin 502 dengan penyebab yang gak masuk akal? Ceritain di kolom komentar, aku penasaran. Kadang penyebab paling aneh justru yang paling seru dibahas — soal socket beda versi aja udah ada ceritanya, apalagi yang lain. Matur nuwun udah baca sampe sini, semoga gak ada lagi panik jam 3 pagi buat sampeyan.