# Arsitektur Background Worker Skala Besar dengan Supervisor dan Redis Queue

> Diterbitkan oleh Literally Web ID pada 20 Oct 2026
> Sumber: https://literally.web.id/articles/arsitektur-background-worker-skala-besar-dengan-supervisor-dan-redis-queue

---

Dalam 15 menit ke depan, kita akan merakit sebuah sistem background worker yang tangguh, tahan banting, dan siap menghadapi beban produksi berskala besar menggunakan Supervisor dan Redis. Pengalaman bertahun-tahun di lapangan mengajarkan saya bahwa kegagalan terbesar bukan terletak pada kode aplikasinya, melainkan pada bagaimana proses latar belakang tersebut dikelola saat server mengalami lonjakan traffic atau mendadak kehabisan memori. Mari kita langsung masuk ke dapur produksi dan mulai meraciknya dari nol.

## 1. Menu Kita Hari Ini & Alat yang Perlu Disiapkan

Sebelum kita menyalakan terminal, mari kita pastikan bahan-bahan di atas meja kerja sudah lengkap. Kita tidak akan membuang waktu membahas definisi klise, melainkan langsung menyiapkan infrastruktur yang dibutuhkan oleh backend modern.

Bahan utama yang harus sudah terpasang di server Ubuntu/Debian Anda:
- **Redis Server**: Sebagai broker pesan (message broker) ultra-cepat untuk menampung antrean tugas.
- **Supervisor**: Proses control system untuk memastikan worker kita hidup 24/7 dan otomatis bangkit jika mengalami *crash*.
- **Runtime Backend**: Bisa berupa PHP, Node.js, ataupun Go yang bertindak sebagai eksekutor script worker.

> [!TIP]
> Pastikan Redis Anda sudah dikonfigurasi dengan kebijakan memori yang tepat (misal: `maxmemory-policy noeviction` atau `volatile-lru`) agar task penting tidak terhapus secara sepihak saat Redis mulai kepenuhan.

Dari pengalaman menangani jutaan antrean email, laporan PDF, dan webhook harian, kombinasi Redis dan Supervisor adalah standar industri yang paling minim friksi namun sangat bisa diandalkan. Mari kita petakan bagaimana alur kerja sistem ini sebelum kita menuliskan baris konfigurasi pertama.

## 2. Peta Jalan Singkat: Apa yang Sedang Kita Rakit

Bayangkan sebuah restoran cepat saji. Aplikasi web Anda adalah kasir yang menerima pesanan (dispatch task ke Redis), sementara Redis adalah papan pesanan di dapur. Supervisor bertindak sebagai kepala koki yang memastikan para koki (worker processes) tetap berdiri di posnya, memasak pesanan satu per satu, dan langsung mengganti koki jika ada yang pingsan.

Langkah-langkah yang akan kita lewati secara maraton:
1. Menyiapkan environment Redis dan script worker sederhana.
2. Meracik file konfigurasi Supervisor untuk menghandel multi-process worker (High Availability).
3. Menerapkan strategi *retry* dan *Dead Letter Queue* (DLQ) untuk mengamankan data dari task yang gagal.
4. Melakukan uji coba beban dan verifikasi lapangan.

Transisi mulus ini akan membawa kita langsung ke terminal untuk menyiapkan fondasi pertama.

## 3. Langkah 1: Mempersiapkan Fondasi & Environment

Asumsikan Redis sudah aktif di port default `6379`. Langkah pertama yang sering dilewatkan oleh engineer junior adalah menguji konektivitas dan menyiapkan direktori log yang bersih. Supervisor membutuhkan tempat khusus untuk mencatat keluaran (*stdout* dan *stderr*) dari setiap worker.

Jalankan perintah ini di terminal server Anda untuk membuat struktur direktori log:

```bash
sudo mkdir -p /var/log/supervisor
sudo mkdir -p /var/run/worker-pool
```

Selanjutnya, mari kita buat sebuah script worker tiruan menggunakan PHP atau bahasa pilihan Anda. Script ini bertindak sebagai penerima beban dari Redis Queue. Simpan kode ini di `/var/www/html/worker.php`:

```php
<?php
// worker.php - Sederhana, tangguh, dan siap memproses antrean
require __DIR__ . '/vendor/autoload.php';

$client = new PredisClient();

echo "[Worker] Memulai proses mendengarkan antrean Redis...
";

while (true) {
    // Mengambil task dari list Redis dengan mekanisme blocking (blpop)
    $task = $client->blpop('app_queue', 0);
    $payload = json_decode($task[1], true);

    try {
        echo "[Worker] Memproses task ID: {$payload['id']}
";
        // Simulasi proses berat
        usleep(500000);
        
        if (rand(1, 10) == 5) {
            throw new Exception("Koneksi database terputus sesaat!");
        }

        echo "[Worker] Task ID: {$payload['id']} selesai dengan sukses.
";
    } catch (Exception $e) {
        echo "[ERROR] Gagal memproses task {$payload['id']}: {$e->getMessage()}
";
        // Masukkan ke Dead Letter Queue atau lakukan retry
        pushToDeadLetterQueue($client, $payload);
    }
}

function pushToDeadLetterQueue($client, $payload) {
    $payload['failed_at'] = date('Y-m-d H:i:s');
    $client->rpush('app_queue_dlq', json_encode($payload));
}
```

> [!IMPORTANT]
> Penggunaan fungsi blocking seperti `blpop` pada Redis jauh lebih efisien dibandingkan *polling* berbasis `while(true)` dengan `sleep()`, karena tidak membuang siklus CPU saat antrean kosong.

Setelah fondasi script ini siap, tantangan berikutnya adalah bagaimana menjaga agar script `worker.php` ini tetap hidup meskipun server reboot atau script mengalami *fatal error*. Di sinilah Supervisor menunjukkan tajinya.

## 4. Langkah 2: Meracik Konfigurasi Inti Tanpa Basa-basi

Masuklah ke direktori konfigurasi Supervisor yang biasanya terletak di `/etc/supervisor/conf.d/`. Kita akan membuat file konfigurasi baru bernama `app-worker.conf`. File ini akan mengatur agar sistem menjalankan 4 proses worker secara paralel (skalabilitas horizontal tingkat proses).

Buka editor teks Anda dan masukkan konfigurasi bersih berikut:

```ini
[program:app-background-worker]
command=php /var/www/html/worker.php
autostart=true
autorestart=true
user=www-data
numprocs=4
process_name=%(program_name)s_%(process_num)02d
redirect_stderr=true
stdout_logfile=/var/log/supervisor/app-worker-%(process_num)02d.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
stopwaitsecs=3600
```

Perhatikan parameter `numprocs=4` dan `process_name=%(program_name)s_%(process_num)02d`. Kombinasi maut ini secara otomatis akan menelurkan 4 instance worker terpisah (`app-background-worker_00`, `app-background-worker_01`, dst) yang dikelola secara independen. Jika salah satu worker mengalami *segfault* atau *out of memory*, Supervisor akan langsung membangkitkannya kembali dalam hitungan milidetik.

> [!WARNING]
> Pastikan direktori log yang Anda tentukan (`/var/log/supervisor/`) memiliki izin (*permissions*) yang sesuai dengan user yang menjalankan proses (`user=www-data`). Jika salah setting permission, Supervisor akan gagal meluncurkan worker dan terus-menerus melakukan restart loop.

Simpan file tersebut, lalu beritahu Supervisor untuk memuat ulang konfigurasinya dengan perintah kilat:

```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start app-background-worker:*
```

Konfigurasi inti sudah terpasang rapi. Sebelum kita menutup sesi dapur ini, mari kita perkuat sistem dengan strategi pengamanan lanjutan agar aplikasi kita memiliki ketahanan kelas enterprise.

## 5. Langkah 3: Sentuhan Akhir Keamanan & Optimasi

Dalam lingkungan produksi nyata, kegagalan jaringan atau bug logika *software* tidak boleh membuat aplikasi kolaps. Di sinilah kita membutuhkan strategi *Retry* berbasis *Exponential Backoff* dan *Dead Letter Queue* (DLQ).

Jika sebuah task gagal karena timeout API pihak ketiga, jangan langsung membuangnya. Masukkan kembali ke antrean utama dengan *delay* tertentu, atau jika sudah gagal hingga 3 kali, lempar ke `app_queue_dlq` untuk diinvestigasi oleh tim engineer.

Selain itu, optimalkan konfigurasi Redis Anda di `/etc/redis/redis.conf` untuk menangani beban tinggi:

```text
# Batasi penggunaan memori agar tidak OOM Killer kernel Linux
maxmemory 2gb
maxmemory-policy volatile-lru

# Tingkatkan performa disk I/O snapshotting
save 900 1
save 300 10
```

Dengan optimasi ini, memori server Anda aman dari kebocoran data, dan worker dapat berjalan tanpa hambatan performa. Mari kita uji racikan kita sekarang.

## 6. Tes Rasa: Memastikan Semuanya Berjalan Sempurna

Saatnya melakukan uji coba langsung di lapangan untuk melihat apakah racikan kita berfungsi sesuai harapan.

Pertama, cek status Supervisor dengan perintah:

```bash
sudo supervisorctl status
```

Anda akan melihat output seperti ini yang menandakan 4 worker sedang berjalan dengan status `RUNNING`:

```text
app-background-worker:app-background-worker_00   RUNNING   pid 14202, uptime 0:02:15
app-background-worker:app-background-worker_01   RUNNING   pid 14203, uptime 0:02:15
app-background-worker:app-background-worker_02   RUNNING   pid 14204, uptime 0:02:15
app-background-worker:app-background-worker_03   RUNNING   pid 14205, uptime 0:02:15
```

Kedua, mari kirimkan task dummy ke Redis menggunakan CLI Redis untuk melihat worker langsung bereaksi:

```bash
redis-cli lpush app_queue '{"id": 1001, "task": "send_welcome_email\