# Mengelola Background Job Skala Enterprise dengan Redis dan Supervisor

> Diterbitkan oleh Literally Web ID pada 20 Oct 2026
> Sumber: https://literally.web.id/articles/mengelola-background-job-skala-enterprise-dengan-redis-dan-supervisor

---

## 1. Alarm Tengah Malam: Saat Layanan Produksi Mulai Tumbang

Pukul 02:30 WIB. PagerDuty saya menjerit melengking, membangunkan saya dari tidur lelap. Layar ponsel langsung dibanjiri notifikasi dari Prometheus dan Grafana: *CPU Usage 99%*, *Redis Memory Exhausted*, dan *Webhook Delivery Failure Rate > 80%*. Sebagai Senior Staff Engineer yang malam itu memegang jadwal on-call, saya tahu persis malam yang tenang ini baru saja berubah menjadi mimpi buruk.

Di balik layar, sistem kami yang mengandalkan tumpukan teknologi modern—backend PHP dengan Laravel, antrean pesan berbasis Redis, dan proses worker yang diatur oleh Supervisor di atas infrastruktur Ubuntu Linux—tengah sekarat. Ratusan ribu data *checkout* e-commerce tertahan, email konfirmasi pembayaran macet, dan notifikasi real-time via WebSocket terputus total. Pelanggan mulai mengeluh di media sosial, dan setiap detik penundaan berarti kerugian finansial yang nyata.

Sistem message queue yang seharusnya menjadi penyelamat untuk memisahkan beban sinkronus dan asinkronus justru menjadi titik kegagalan utama (*single point of failure*). Mari kita telusuri bagaimana tumpukan teknologi yang tampak kokoh ini bisa bertekuk lutut di tengah malam, dan bagaimana kita membongkar masalahnya dari akar hingga tuntas.

## 2. Jejak Digital: Menelusuri Anomali Log & Lonjakan Metrik

Begitu membuka terminal dan masuk ke server produksi melalui SSH, langkah pertama saya bukanlah langsung melakukan *restart*—pantang hukumnya bagi seorang arsitek menyentuh tombol panik sebelum memegang data forensik. Saya langsung meluncur ke direktori log Supervisor dan Redis untuk melihat apa yang sebenarnya terjadi.

```bash
# Memeriksa status proses worker yang dikelola oleh Supervisor
sudo supervisorctl status

# Memantau log error worker secara real-time
tail -f /var/log/supervisor/worker-stderr.log
```

Hasilnya mencengangkan. Ratusan proses worker PHP sedang mengalami *segmentation fault* dan keluar dengan kode error tak dikenal, sementara log Redis menunjukkan lonjakan masif pada *used_memory* yang menyentuh batas maksimal RAM server (OOM Killer mulai beraksi). Mari kita intip bagaimana konfigurasi Supervisor yang kami gunakan sebelum insiden ini terjadi:

```ini
[program:ecommerce-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --queue=high,default --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/log/supervisor/worker.log
stopwaitsecs=3600
```

> [!WARNING]
> Konfigurasi `numprocs=8` dengan perintah `queue:work` tanpa manajemen memori yang ketat adalah bom waktu pada aplikasi berbasis bahasa dengan *garbage collection* dinamis seperti PHP. Setiap worker memuat seluruh framework ke dalam memori, dan jika ada *memory leak* kecil pada *job* tertentu, akumulasinya akan menghancurkan server dalam hitungan jam.

Lonjakan trafik kampanye tengah malam membuat jutaan *job* masuk ke Redis secara bersamaan. Karena worker sibuk memproses *job* berat yang memakan waktu lama, antrean menumpuk, memori Redis meluber, dan Supervisor secara agresif mencoba menghidupkan kembali worker yang *crash*, memperparah beban CPU secara eksponensial. Transisi dari lonjakan trafik normal menuju kelumpuhan sistem ini berakar pada kesalahan arsitektural mendasar yang luput dari pengujian beban.

## 3. Membongkar Biang Kerok: Akar Masalah yang Sebenarnya

Setelah menarik napas dalam-dalam dan menganalisis *core dump* serta metrik dari Prometheus, kami menemukan tiga biang kerok utama yang berkolaborasi merobohkan infrastruktur kami:

1. **Memory Leak pada Job Pemrosesan Gambar dan PDF:** Beberapa *job* latar belakang yang bertugas menghasilkan faktur PDF menggunakan pustaka pihak ketiga tidak membebaskan memori objek DOM secara eksplisit setelah selesai.
2. **Kurangnya Pengaturan `maxmemory-policy` di Redis:** Redis dikonfigurasi tanpa kebijakan eviksi memori yang tepat (`noeviction`), sehingga ketika RAM habis, Redis menolak semua perintah tulis baru, membuat seluruh aplikasi web gagal melakukan *dispatch* antrean.
3. **Konfigurasi `stopwaitsecs` yang Terlalu Panjang:** Supervisor disetel menunggu hingga 1 jam (`3600` detik) saat proses penghentian, membuat prosesor terkunci saat terjadi antrean sinyal *SIGTERM* massal.

Mari bandingkan pendekatan lama yang rapuh dengan arsitektur defensif yang seharusnya kita terapkan:

| Komponen | Pendekatan Lama (Rapuh) | Pendekatan Baru (Resilien) |
| :--- | :--- | :--- |
| **Redis Memory** | `noeviction` (Crash saat penuh) | `allkeys-lru` / `volatile-lru` |
| **Worker Lifecycle** | `queue:work` (Menahan memori selamanya) | `queue:listen` atau batasan `--max-jobs` & `--max-time` |
| **Supervisor Numprocs** | Statis (`numprocs=8` tanpa batas beban) | Dinamis berdasarkan kapasitas core CPU |

Pemahaman mendalam terhadap perilaku Redis dan Supervisor ini menuntun kita pada tindakan penyelamatan darurat yang harus dieksekusi seketika di lapangan.

## 4. Tindakan Darurat: Menghidupkan Kembali Layanan dalam Hitungan Menit

Kepanikan tidak akan menyelesaikan masalah; eksekusi perintah terminal yang presisi dan terukur adalah satu-satunya jalan keluar. Berikut adalah *Emergency Runbook* one-liner siap salin yang saya eksekusi malam itu untuk menstabilkan sistem dalam waktu kurang dari 60 detik:

```bash
# 1. Hentikan seluruh worker Supervisor secara paksa untuk menghentikan lonjakan CPU
sudo supervisorctl stop ecommerce-worker:*

# 2. Bersihkan antrean yang rusak atau lakukan flush pada Redis jika data sudah stale (Gunakan dengan hati-hati!)
redis-cli -a "secure_password_here" FLUSHDB

# 3. Sesuaikan konfigurasi Redis agar langsung menendang key lama jika memori hampir penuh
echo "maxmemory 2gb" | sudo tee -a /etc/redis/redis.conf
echo "maxmemory-policy allkeys-lru" | sudo tee -a /etc/redis/redis.conf
sudo systemctl restart redis-server

# 4. Perbarui file konfigurasi Supervisor dengan batasan job per worker untuk mencegah memory leak
# (Edit /etc/supervisor/conf.d/worker.conf dengan menambahkan --max-jobs=100 --max-time=3600)

# 5. Muat ulang konfigurasi Supervisor dan jalankan kembali worker dengan aman
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start ecommerce-worker:*
```

> [!TIP]
> Selalu gunakan opsi `--max-jobs` dan `--max-time` pada perintah worker Laravel atau *queue runner* bahasa lain. Ini memaksa worker untuk keluar secara anggun (*graceful exit*) setelah menyelesaikan sejumlah *job* tertentu, memberikan kesempatan kepada sistem operasi untuk membersihkan memori yang mungkin bocor.

Sistem berangsur pulih. Grafik latensi di Grafana mulai turun dari zona merah ke zona hijau, dan antrean *checkout* kembali berjalan lancar. Namun, pekerjaan seorang arsitek belum selesai di sini; kita harus memastikan insiden serupa tidak terulang kembali melalui kebijakan retrospektif yang ketat.

## 5. Kebijakan Retrospektif: Menambal Celah agar Tak Pernah Terulang

Pelajaran pahit malam itu memaksa kami merombak total standar operasional prosedur pengembangan backend dan infrastruktur. Kami tidak bisa lagi mempercayakan stabilitas sistem hanya pada keberuntungan.

Pertama, kami menerapkan aturan ketat dalam *Code Review* bahwa setiap *job* latar belakang yang melakukan operasi berat (seperti manipulasi gambar, ekspor laporan besar, atau panggilan API eksternal) wajib dipecah menjadi *chunk* kecil atau dijalankan di *queue* terpisah dengan prioritas rendah. Kedua, kami mengubah konfigurasi Supervisor agar menggunakan batasan otomatis:

```ini
[program:ecommerce-worker-resilient]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --queue=high,default --tries=3 --max-jobs=500 --max-time=1800 --memory=512
autostart=true
autorestart=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/log/supervisor/worker-resilient.log
stopwaitsecs=60
```

Dengan parameter `--memory=512`, proses worker akan otomatis mematikan dirinya sendiri jika konsumsi RAM melewati 512MB, dan Supervisor akan dengan sigap menghidupkannya kembali sebagai proses baru yang bersih. Arsitektur defensif ini memastikan bahwa *memory leak* tidak akan pernah lagi berujung pada kelumpuhan total server.

## 6. Pasang Alarm: Otomasi Deteksi Dini untuk Tim On-Call

Agar tidak ada lagi alarm tengah malam yang mengejutkan tanpa persiapan, kami memperketat sistem observabilitas. Kami memasang aturan *alerting* baru di Prometheus dan Alertmanager yang langsung terintegrasi dengan webhook PagerDuty dan Slack:

- **Peringatan Dini (Warning):** Jika penggunaan memori Redis mencapai 80%, atau jika jumlah *job* yang gagal (*failed jobs*) melebihi 50 dalam kurun waktu 5 menit, kirim notifikasi ke channel Slack `#ops-warning`.
- **Kritis (Critical):** Jika Redis mencapai status *OOM*, atau jika seluruh proses Supervisor dalam keadaan *STOPPED* selama lebih dari 30 detik, bangunkan tim on-call melalui panggilan telepon otomatis.

Dengan fondasi arsitektur antrean yang tangguh, konfigurasi Supervisor yang disiplin, serta sistem pemantauan proaktif, kami kini dapat tidur dengan nyenyak, mengetahui bahwa infrastruktur skala enterprise kami siap menghadapi badai trafik apa pun di masa depan.