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.

Background Jobs Rails di 2026: Sidekiq vs Good Job dan Pertanyaan Interview

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 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 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.

Siap menguasai wawancara Ruby on Rails Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Good Job 4.x: Batch dan Uniqueness Native PostgreSQL

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 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

FiturSidekiq 8.xGood Job 4.xSolid Queue 1.x
BackendRedis 7.2+PostgreSQLPostgreSQL/MySQL/SQLite
BatchesPro/EnterpriseTermasukDirencanakan
Unique jobsEnterpriseTermasukManual via locks
Cron schedulingEnterpriseTermasukVia solid_queue_cron
Web UITermasukTermasukMinimal (Mission Control)
Batas throughput100k+ jobs/min10k jobs/min10k jobs/min
Embed di PumaYa (8.x)TidakYa
LisensiLGPL + CommercialMITMIT

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

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

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
Tantangan harian

Bisakah kamu menemukan bug di Ruby on Rails?

Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Anthony Fillion-Maillet

Ditulis oleh

Anthony Fillion-Maillet

Pendiri SharpSkill

Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.

Diperbarui 12 September 2026

Bagikan

Artikel terkait