# Background Jobs Rails di 2026: Sidekiq vs Good Job dan Pertanyaan Interview > Panduan lengkap memilih queue backend untuk Rails: perbandingan Sidekiq 8.x, Good Job 4.x, dan Solid Queue dengan fokus pada throughput, fitur, dan pertanyaan interview teknis. - Published: 2026-09-12 - Updated: 2026-09-12 - Author: Anthony Fillion-Maillet - Reading time: 5 min --- Background jobs di Rails telah berkembang signifikan dengan hadirnya Rails 8.x dan diperkenalkannya Solid Queue sebagai backend Active Job default. Pemilihan antara Sidekiq, Good Job, dan Solid Queue bergantung pada kebutuhan throughput, batasan infrastruktur, dan fitur yang diperlukan oleh setiap proyek. > **Panduan Keputusan Cepat** > > Untuk proyek Rails 8 baru, mulailah dengan Solid Queue. Beralih ke Sidekiq untuk workload tinggi yang melebihi 100.000 jobs/hari atau ketika latensi tingkat Redis diperlukan. Pilih Good Job untuk jobs berbasis PostgreSQL dengan fitur batch dan unique job constraints tanpa biaya lisensi. ## Bagaimana Active Job Menyatukan Background Processing Active Job menyediakan interface standar untuk mendeklarasikan, mengantrekan, dan mengeksekusi pekerjaan background di Rails. Framework ini mengabstraksi perbedaan antar queue backend, memungkinkan kode tetap portabel di Sidekiq, Good Job, Solid Queue, atau adapter lainnya. ```ruby # app/jobs/payment_processor_job.rb class PaymentProcessorJob < ApplicationJob queue_as :critical retry_on Stripe::RateLimitError, wait: :polynomially_longer, attempts: 5 discard_on Stripe::InvalidRequestError def perform(order_id) order = Order.find(order_id) PaymentService.process(order) OrderMailer.confirmation(order).deliver_later end end ``` Callback `retry_on` dan `discard_on` menangani kegagalan sementara dan error permanen tanpa kode spesifik backend. Direktif `queue_as` menetapkan prioritas, yang diinterpretasikan oleh setiap backend sesuai strategi pemrosesan queue masing-masing. ## Sidekiq 8.x: Throughput Berbasis Redis [Sidekiq](https://github.com/sidekiq/sidekiq) tetap menjadi baseline performa untuk background jobs Rails. Seri rilis 8.x memerlukan Ruby 3.2+, Rails 7.0+, dan Redis 7.2+ (Valkey dan Dragonfly dapat digunakan sebagai pengganti langsung sejak Redis mengubah lisensinya). ```ruby # config/initializers/sidekiq.rb Sidekiq.configure_server do |config| config.redis = { url: ENV.fetch('REDIS_URL') } config.concurrency = 10 end Sidekiq.configure_client do |config| config.redis = { url: ENV.fetch('REDIS_URL') } end ``` Sidekiq 8 membawa tiga perubahan utama: Web UI yang ditulis ulang dari awal mengurangi CSS dari 160KB menjadi 16KB dan waktu render halaman rata-rata dari 55ms menjadi 3ms, job profiling dengan [Vernier](https://github.com/jhawthorn/vernier) di tab Profiles baru, dan job metrics yang disimpan hingga 72 jam. ### Kapan Sidekiq Tepat Digunakan Sidekiq cocok untuk workload yang membutuhkan throughput berkelanjutan, latensi pickup job sub-milidetik, atau fitur enterprise seperti rate limiting dan unique jobs yang membenarkan penggunaan Redis. Capsules, yang diperkenalkan di 7.0 dan sekarang menjadi standar, memungkinkan satu proses Sidekiq menjalankan beberapa thread pool terisolasi dengan concurrency dan queue masing-masing. ```ruby # config/sidekiq.yml :concurrency: 10 :queues: - [critical, 3] - [default, 2] - [low, 1] # Capsules untuk pemrosesan terisolasi :capsules: imports: :concurrency: 2 :queues: - imports ``` API embedding juga memungkinkan Sidekiq berjalan di dalam proses Puma untuk aplikasi kecil, mirip dengan cara plugin Puma Solid Queue bekerja. ## Good Job 4.x: Batch dan Uniqueness Native PostgreSQL [Good Job](https://github.com/bensheldon/good_job) menggunakan LISTEN/NOTIFY PostgreSQL untuk pickup job dan advisory locks untuk keamanan run-once. Versi 4.19.x (terkini per September 2026) mendukung Rails 6.1+ dan Ruby 3.0+. ```ruby # config/application.rb config.active_job.queue_adapter = :good_job # config/initializers/good_job.rb Rails.application.configure do config.good_job.execution_mode = :async config.good_job.max_threads = 5 config.good_job.poll_interval = 5 config.good_job.shutdown_timeout = 25 end ``` Good Job menyediakan batches dan unique jobs di tier open-source, fitur yang Sidekiq cadangkan untuk lisensi berbayar. Panggilan `perform_later` menyisipkan baris ke tabel `good_jobs` dalam transaksi database yang sama dengan kode pemanggil, sehingga jika transaksi rollback, job tidak pernah dibuat. ### Batches Tanpa Lisensi ```ruby # app/jobs/batch_import_job.rb class BatchImportJob < ApplicationJob def perform(batch, params) batch.on(:finish, ImportCompletionJob, params) params[:file_ids].each do |file_id| batch.add do ProcessFileJob.perform_later(file_id) end end end end # Enqueue batch GoodJob::Batch.enqueue do |batch| BatchImportJob.perform_later(batch, file_ids: [1, 2, 3]) end ``` ### Unique Jobs untuk Idempotency ```ruby # app/jobs/sync_inventory_job.rb class SyncInventoryJob < ApplicationJob include GoodJob::ActiveJobExtensions::UniqueJob good_job_control_concurrency_with( perform_limit: 1, key: -> { "sync_inventory_#{arguments.first}" }, duration: 1.hour ) def perform(warehouse_id) InventorySync.run(warehouse_id) end end ``` Kendala `perform_limit: 1` memastikan hanya satu sync berjalan per warehouse pada satu waktu, mencegah pekerjaan duplikat ketika job yang sama di-enqueue beberapa kali. ## Solid Queue: Default Rails 8 [Solid Queue](https://github.com/rails/solid_queue) menyimpan jobs di database aplikasi menggunakan `FOR UPDATE SKIP LOCKED`, fitur PostgreSQL dan MySQL yang mengubah tabel biasa menjadi job queue. Aplikasi Rails 8 baru sudah dikonfigurasi dengan Solid Queue secara default. ```ruby # config/solid_queue.yml production: dispatchers: - polling_interval: 1 batch_size: 500 workers: - queues: "*" threads: 5 polling_interval: 0.1 ``` Solid Queue dapat berjalan di dalam proses web server Puma dengan `SOLID_QUEUE_IN_PUMA=true`, yang menyederhanakan deployment untuk aplikasi yang tidak memerlukan proses worker terpisah. Jobs bertahan di tabel database, bertahan dari restart proses dan deployment tanpa dependensi eksternal. ## Tabel Perbandingan Fitur | Fitur | Sidekiq 8.x | Good Job 4.x | Solid Queue 1.x | |-------|-------------|--------------|------------------| | Backend | Redis 7.2+ | PostgreSQL | PostgreSQL/MySQL/SQLite | | Batches | Pro/Enterprise | Termasuk | Direncanakan | | Unique jobs | Enterprise | Termasuk | Manual via locks | | Cron scheduling | Enterprise | Termasuk | Via solid_queue_cron | | Web UI | Termasuk | Termasuk | Minimal (Mission Control) | | Batas throughput | 100k+ jobs/min | 10k jobs/min | 10k jobs/min | | Embed di Puma | Ya (8.x) | Tidak | Ya | | Lisensi | LGPL + Commercial | MIT | MIT | ## Pertanyaan Interview tentang Rails Background Jobs Interview teknis sering menguji pemahaman tentang reliabilitas job, strategi retry, dan keputusan arsitektur. Berikut pertanyaan yang membedakan kandidat berpengalaman. ### Q1: Apa perbedaan `retry_on` dengan logika retry spesifik backend? `retry_on` adalah callback Active Job yang bekerja di semua backend. Callback ini menangkap exception spesifik, menerapkan strategi wait (`:polynomially_longer` mundur secara eksponensial), dan meng-enqueue ulang job. Logika retry spesifik backend, seperti `sidekiq_retry_in` Sidekiq, hanya bekerja dengan backend tersebut dan dapat meng-override perilaku Active Job. ```ruby # Active Job retry (portabel) class ApiSyncJob < ApplicationJob retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 8 def perform(record_id) ExternalApi.sync(record_id) end end ``` ### Q2: Apa yang terjadi pada job jika transaksi database yang meng-enqueue-nya rollback? Dengan queue berbasis database (Good Job, Solid Queue), baris job adalah bagian dari transaksi, sehingga rollback bersama yang lainnya. Dengan queue berbasis Redis (Sidekiq), job sudah ada di Redis sebelum transaksi selesai, menciptakan orphaned jobs. Solusinya adalah callback `after_commit`: ```ruby # Pola benar untuk Sidekiq class Order < ApplicationRecord after_commit :enqueue_confirmation, on: :create private def enqueue_confirmation OrderConfirmationJob.perform_later(id) end end ``` ### Q3: Kapan Good Job lebih unggul dari Sidekiq? Good Job lebih unggul dari Sidekiq ketika biaya operasional Redis melebihi manfaat throughput-nya. Untuk aplikasi yang memproses kurang dari 50.000 jobs/hari, queue berbasis PostgreSQL menghindari kompleksitas infrastruktur, monitoring, dan failover dari cluster Redis terpisah. Good Job juga menyediakan batches dan unique jobs tanpa biaya lisensi, yang penting untuk tim yang membutuhkan fitur tersebut dengan anggaran terbatas. ### Q4: Jelaskan idempotency job dan mengapa penting untuk retry Idempotency berarti menjalankan job yang sama beberapa kali menghasilkan hasil yang sama seperti menjalankannya sekali. Jobs harus idempotent karena kegagalan jaringan, crash proses, atau penanganan timeout dapat menyebabkan eksekusi duplikat. Tekniknya termasuk unique constraints di database, memeriksa hasil yang sudah ada sebelum memproses, dan menggunakan idempotency keys eksternal untuk API pembayaran. ```ruby # Pemrosesan pembayaran idempotent def perform(order_id, idempotency_key) return if Payment.exists?(idempotency_key: idempotency_key) Payment.create!( order_id: order_id, idempotency_key: idempotency_key, amount: Order.find(order_id).total ) end ``` ### Q5: Bagaimana menangani jobs yang harus berjalan tepat sekali di seluruh distributed workers? Distributed locks mencegah eksekusi bersamaan. Good Job menggunakan advisory locks PostgreSQL. Sidekiq Enterprise menawarkan unique jobs. Untuk implementasi manual, gunakan Redis `SETNX` atau PostgreSQL `pg_try_advisory_lock`: ```ruby class ExclusiveJob < ApplicationJob def perform(resource_id) lock_key = "exclusive_job:#{resource_id}" ActiveRecord::Base.connection.execute( "SELECT pg_try_advisory_lock(hashtext('#{lock_key}'))" ).first['pg_try_advisory_lock'] or return begin process_resource(resource_id) ensure ActiveRecord::Base.connection.execute( "SELECT pg_advisory_unlock(hashtext('#{lock_key}'))" ) end end end ``` ## Memilih Backend yang Tepat untuk Rails Background Jobs - Mulai dengan Solid Queue untuk proyek Rails 8 baru yang belum memiliki Redis di stack - Beralih ke Sidekiq ketika volume job melebihi 50.000/hari atau latensi pickup di bawah 100ms diperlukan - Pilih Good Job untuk deployment PostgreSQL-only yang membutuhkan batches, unique jobs, atau cron scheduling tanpa biaya lisensi - Gunakan callback `after_commit` ketika meng-enqueue jobs dengan Sidekiq untuk menghindari orphaned jobs pada rollback transaksi - Buat setiap job idempotent karena retry dan distributed processing dapat menyebabkan eksekusi duplikat - Untuk interview, tunjukkan pemahaman tentang transactional job enqueuing, strategi retry, dan pola distributed locking --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/ruby-on-rails/rails-background-jobs-sidekiq-good-job-comparison