Background Jobs in Rails: Kiezen tussen Solid Queue en Sidekiq in 2026
Vorige week belde een klant met een bekend probleem. Hun Rails-app genereerde PDF-rapporten in de request-cycle. Gebruikers klikten op “Genereer Rapport” en staarden veertig seconden naar een spinner. Soms liep het request vast. Soms doodde Heroku de dyno. De oplossing was duidelijk: verplaats het naar een background job. De vervolgvraag was minder duidelijk: welke backend?
Twee jaar geleden was het antwoord bijna altijd Sidekiq. In 2026 heeft Solid Queue het gesprek veranderd.
Wat Solid Queue werkelijk is
Solid Queue werd meegeleverd met Rails 8 als de standaard Active Job backend. Het slaat jobs op in je bestaande database met FOR UPDATE SKIP LOCKED — een PostgreSQL- en MySQL-feature die een gewone tabel verandert in een verrassend capabele job queue.
Geen Redis. Geen extra infrastructuur. Jobs leven in dezelfde database als al het andere.
# Dat is het. Dit is nu je queue.
class ReportJob < ApplicationJob
queue_as :default
def perform(report_id)
report = Report.find(report_id)
report.generate_pdf
ReportMailer.ready(report).deliver_now
end
end
Als je al PostgreSQL draait, werkt Solid Queue direct. Je krijgt transactionele enqueuing — de job bestaat alleen als de transactie die hem aanmaakte gecommit wordt. Geen phantom jobs meer die verwijzen naar records die zijn teruggedraaid.
Wanneer Sidekiq nog steeds wint
Redis is snel. Absurd snel voor deze workload. Sidekiq verwerkt duizenden jobs per seconde op bescheiden hardware. Als je app miljoenen jobs per dag in de queue plaatst, handelt Sidekiq dat moeiteloos af.
Sidekiq Pro en Enterprise voegen features toe die ertoe doen op schaal: rate limiting, unieke jobs, batches met callbacks. Een facturatiesysteem dat ‘s nachts 50.000 facturen verwerkt en moet weten wanneer de hele batch klaar is? Sidekiq Enterprise batches lossen dat netjes op.
batch = Sidekiq::Batch.new
batch.on(:success, InvoiceBatchCallback, 'run_id' => run.id)
batch.jobs do
invoices.each { |inv| InvoiceJob.perform_async(inv.id) }
end
Solid Queue heeft geen equivalent. Je zou het zelf bouwen met tellers en callbacks, en je zou het minstens één keer fout doen.
Het beslissingskader
Zo loop ik dit met klanten door:
Kies Solid Queue wanneer:
- Je minder dan 10.000 jobs per uur verwerkt
- Je al PostgreSQL draait en geen Redis wilt beheren
- Transactionele enqueuing belangrijk is (e-commerce, financiële apps)
- Je team klein is en operationele eenvoud wint
- Je op Rails 8 zit en helemaal opnieuw begint
Kies Sidekiq wanneer:
- De doorvoervraag hoog is (miljoenen jobs per dag)
- Je batches, rate limiting of unieke jobs nodig hebt
- Redis al in je stack zit voor caching of pub/sub
- Job-latentie onder 100ms belangrijk is
- Je het team hebt om Redis goed te monitoren
De verkeerde reden om een van beide te kiezen: omdat een blogpost het zei. Meet je werkelijke volume. De meeste Rails-apps verwerken een paar duizend jobs per dag. Op die schaal maakt de backend nauwelijks uit.
Patronen die er altijd toe doen
Welke backend je ook kiest, deze patronen besparen je nachtelijke telefoontjes.
Maak jobs idempotent
Jobs gaan opnieuw draaien. Netwerken falen, databases haperen, deploys herstarten workers halverwege de uitvoering. Als een job twee keer draaien slechte resultaten oplevert, heb je een bug.
class ChargeCustomerJob < ApplicationJob
def perform(order_id)
order = Order.find(order_id)
return if order.charged?
charge = Stripe::Charge.create(
amount: order.total_cents,
customer: order.stripe_customer_id,
idempotency_key: "order-#{order.id}"
)
order.update!(
charged: true,
stripe_charge_id: charge.id
)
end
end
De guard clause en de Stripe idempotency key werken samen. Draai dit tien keer, de klant wordt één keer belast.
Gebruik aparte queues met een doel
Eén queue is een file die staat te wachten. Een bulk e-mailverzending met 100.000 jobs mag een wachtwoord-reset e-mail niet blokkeren.
# config/solid_queue.yml (of sidekiq.yml equivalent)
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: [critical]
threads: 3
processes: 1
- queues: [default, mailers]
threads: 5
processes: 2
- queues: [bulk]
threads: 10
processes: 1
Kritieke jobs krijgen hun eigen workers. Bulkverwerking kan interactief werk niet uithongeren. Pas threadaantallen aan op basis van of jobs I/O-bound of CPU-bound zijn.
Stel timeouts in
Een job zonder timeout is een resource-lek in wording. Externe API-calls hangen. Database-queries gaan de mist in. Stel grenzen.
class ExternalApiJob < ApplicationJob
limits_concurrency to: 5, key: ->(api_name) { api_name }
def perform(api_name, payload)
Timeout.timeout(30) do
ExternalApi.call(api_name, payload)
end
rescue Timeout::Error
Rails.logger.warn "API call to #{api_name} timed out"
raise # Laat het retry-mechanisme het afhandelen
end
end
Monitor de juiste dingen
Queue-diepte is belangrijker dan doorvoer. Een queue die sneller groeit dan hij leegloopt, vreet uiteindelijk al je geheugen of schijfruimte op. Stel alerts in op queue-diepte, niet alleen foutpercentages. Combineer dit met gestructureerde logging zodat je individuele job-failures kunt herleiden naar het request dat ze in de queue plaatste.
Voor Solid Queue: houd de grootte van de solid_queue_ready_executions-tabel in de gaten. Voor Sidekiq toont het dashboard het, of haal het op via de API:
# Health check endpoint
Sidekiq::Queue.all.each do |queue|
if queue.size > 1000
Alerting.warn("Queue #{queue.name} depth: #{queue.size}")
end
end
Migratiepad
Al op Sidekiq en overweeg je Solid Queue? Draai ze naast elkaar. Route nieuwe, low-volume jobs naar Solid Queue. Houd high-throughput jobs op Sidekiq. Active Job’s adapter-per-queue ondersteuning maakt dit eenvoudig:
class LowVolumeJob < ApplicationJob
self.queue_adapter = :solid_queue
queue_as :default
end
class HighThroughputJob < ApplicationJob
self.queue_adapter = :sidekiq
queue_as :processing
end
Geef het een maand. Bekijk de metrics. Besluit dan of de volledige migratie de moeite waard is.
De fractional CTO-blik
De meeste background job-problemen zijn geen backend-problemen. Het zijn ontwerpproblemen. Jobs die te veel doen. Jobs die niet idempotent zijn. Jobs zonder timeouts of monitoring. Los die eerst op. De backend-keuze is secundair.
Als je een nieuw Rails 8-project start, gebruik Solid Queue. Eén stuk infrastructuur minder, transactionele garanties, en genoeg performance voor 95% van de applicaties. Als je eruit groeit, is Sidekiq een beproefd upgradepad.
Als je jobs deployt als onderdeel van een CI/CD pipeline, zorg er dan voor dat je testsuite de job-logica direct test — test niet alleen dat hij in de queue geplaatst wordt.
Over-engineer de queue niet. Ship de feature. Bekijk de metrics. Pas aan wanneer de realiteit het vereist.
Veelgestelde Vragen
Kan Solid Queue geplande of terugkerende jobs aan?
Ja. Solid Queue ondersteunt terugkerende taken via de ingebouwde scheduler. Definieer ze in config/solid_queue.yml onder de dispatchers sectie. Voor eenmalige geplande jobs gebruik je perform_later met Active Job’s set(wait:) of set(wait_until:) — Solid Queue slaat het geplande tijdstip op in de database en pikt ze op wanneer het zover is.
Wat gebeurt er met jobs wanneer ik deploy met Solid Queue?
Solid Queue workers maken hun huidige job af voordat ze afsluiten op SIGTERM. Onafgemaakte jobs blijven in de database en worden opgepikt door nieuwe workers na de deploy. Stel een redelijke timeout in op je deployproces zodat workers niet halverwege een job worden afgekapt met SIGKILL.
Moet ik Active Job of Sidekiq’s native API gebruiken?
Gebruik Active Job als je backend-portabiliteit wilt (wisselen tussen Solid Queue en Sidekiq) of als je op Rails 8 zit met Solid Queue. Gebruik Sidekiq’s native API als je Sidekiq-specifieke features nodig hebt zoals batches of rate limiting. Beide mixen in dezelfde app is prima — wees alleen consistent binnen elke job-class.
About the Author
Roger Heykoop is een senior Ruby on Rails ontwikkelaar met 19+ jaar Rails ervaring en 35+ jaar ervaring in softwareontwikkeling. Hij is gespecialiseerd in Rails modernisering, performance optimalisatie, en AI-ondersteunde ontwikkeling.
Get in TouchRelated Articles
Need Expert Rails Development?
Let's discuss how we can help you build or modernize your Rails application with 19+ years of expertise
Schedule a Free Consultation