Jobs em segundo plano no Rails em 2026: Sidekiq vs Good Job e perguntas de entrevista
Comparação completa entre Sidekiq, Good Job e Solid Queue para tarefas assíncronas no Rails, com as perguntas técnicas mais frequentes em entrevistas.

Os jobs em segundo plano no Rails evoluíram significativamente com o Rails 8.x e a introdução do Solid Queue como backend padrão do Active Job. A escolha entre Sidekiq, Good Job e Solid Queue depende dos requisitos de throughput, das restrições de infraestrutura e das funcionalidades que cada projeto necessita.
Para novos projetos Rails 8, o recomendado é começar com Solid Queue. Sidekiq é a escolha adequada para cargas de trabalho de alto throughput que ultrapassam 100.000 jobs por dia ou quando a latência no nível do Redis é crítica. Good Job é ideal para jobs armazenados no PostgreSQL com suporte nativo a batches e restrições de unicidade.
Como o Active Job unifica o processamento em segundo plano
O Active Job fornece uma interface padronizada para declarar, enfileirar e executar trabalho em segundo plano no Rails. O framework abstrai as diferenças entre os backends de fila, permitindo que o código permaneça portável entre Sidekiq, Good Job, Solid Queue ou qualquer outro adaptador.
# 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
endOs callbacks retry_on e discard_on tratam falhas transitórias e erros permanentes sem código específico do backend. A diretiva queue_as atribui prioridade, que cada backend interpreta de acordo com sua própria estratégia de processamento de filas.
Sidekiq 8.x: throughput otimizado com Redis
Sidekiq continua sendo a referência de desempenho para jobs em segundo plano no Rails. A série 8.x requer Ruby 3.2+, Rails 7.0+ e Redis 7.2+ (Valkey e Dragonfly funcionam como substitutos diretos desde que o Redis mudou sua licença).
# 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') }
endO Sidekiq 8 trouxe três mudanças importantes: uma interface Web reescrita do zero reduzindo o CSS de 160KB para 16KB e o tempo médio de renderização de 55ms para 3ms, profiling de jobs com Vernier acessível através de uma nova aba Profiles, e retenção de métricas por até 72 horas.
Quando escolher Sidekiq
Sidekiq é apropriado para cargas de trabalho onde throughput sustentado, latência de recuperação de jobs inferior a milissegundo, ou funcionalidades enterprise como rate limiting e jobs únicos justificam a utilização do Redis. As Capsules, introduzidas na versão 7.0 e agora padrão, permitem que um processo Sidekiq execute múltiplos pools de threads isolados com sua própria concorrência e filas.
# config/sidekiq.yml
:concurrency: 10
:queues:
- [critical, 3]
- [default, 2]
- [low, 1]
# Capsules para processamento isolado
:capsules:
imports:
:concurrency: 2
:queues:
- importsA API de embedding também permite executar o Sidekiq dentro do processo Puma para aplicações pequenas, similar ao funcionamento do plugin Puma do Solid Queue.
Pronto para mandar bem nas entrevistas de Ruby on Rails?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Good Job 4.x: batches e unicidade nativas com PostgreSQL
Good Job utiliza LISTEN/NOTIFY do PostgreSQL para recuperação de jobs e advisory locks para garantir execução única. A versão 4.19.x (atual em setembro de 2026) suporta Rails 6.1+ e Ruby 3.0+.
# 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
endO Good Job inclui batches e jobs únicos na versão open-source, funcionalidades que o Sidekiq reserva para licenças pagas. A chamada perform_later insere uma linha na tabela good_jobs dentro da mesma transação de banco de dados que o código chamador, então se a transação for revertida, o job nunca é criado.
Batches sem licença
# 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
# Enfileirar o batch
GoodJob::Batch.enqueue do |batch|
BatchImportJob.perform_later(batch, file_ids: [1, 2, 3])
endJobs únicos para idempotência
# 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
endA restrição perform_limit: 1 garante que apenas uma sincronização seja executada por armazém em qualquer momento, prevenindo trabalho duplicado quando o mesmo job é enfileirado múltiplas vezes.
Solid Queue: o padrão do Rails 8
Solid Queue armazena jobs no banco de dados da aplicação usando FOR UPDATE SKIP LOCKED, uma funcionalidade do PostgreSQL e MySQL que transforma uma tabela regular em uma fila de jobs. Novas aplicações Rails 8 vêm com o Solid Queue configurado por padrão.
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
polling_interval: 0.1O Solid Queue pode ser executado dentro do processo do servidor web Puma com SOLID_QUEUE_IN_PUMA=true, o que simplifica o deploy para aplicações que não precisam de processos worker dedicados. Os jobs persistem nas tabelas do banco de dados, sobrevivendo a reinícios de processos e deploys sem dependências externas.
Tabela comparativa de funcionalidades
| Funcionalidade | Sidekiq 8.x | Good Job 4.x | Solid Queue 1.x |
|---|---|---|---|
| Backend | Redis 7.2+ | PostgreSQL | PostgreSQL/MySQL/SQLite |
| Batches | Pro/Enterprise | Incluído | Planejado |
| Jobs únicos | Enterprise | Incluído | Manual via locks |
| Agendamento cron | Enterprise | Incluído | Via solid_queue_cron |
| Interface Web | Incluída | Incluída | Mínima (Mission Control) |
| Teto de throughput | 100k+ jobs/min | 10k jobs/min | 10k jobs/min |
| Embed no Puma | Sim (8.x) | Não | Sim |
| Licença | LGPL + Comercial | MIT | MIT |
Perguntas de entrevista sobre jobs em segundo plano no Rails
Entrevistas técnicas frequentemente avaliam a compreensão de confiabilidade de jobs, estratégias de retry e decisões arquiteturais. A seguir estão perguntas que distinguem candidatos experientes.
P1: Qual a diferença entre retry_on e a lógica de retry específica do backend?
retry_on é um callback do Active Job que funciona com todos os backends. Ele captura exceções específicas, aplica uma estratégia de espera (:polynomially_longer realiza backoff exponencial) e reenfileira o job. A lógica de retry específica do backend, como sidekiq_retry_in do Sidekiq, só funciona com aquele backend e pode sobrescrever o comportamento do Active Job.
# Retry do Active Job (portável)
class ApiSyncJob < ApplicationJob
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 8
def perform(record_id)
ExternalApi.sync(record_id)
end
endP2: O que acontece com um job se a transação de banco de dados que o enfileirou for revertida?
Com filas baseadas em banco de dados (Good Job, Solid Queue), a linha do job faz parte da transação, então ela é revertida junto com todo o resto. Com filas baseadas em Redis (Sidekiq), o job já está no Redis antes da transação ser completada, criando jobs órfãos. A solução é usar callbacks after_commit:
# Padrão correto para Sidekiq
class Order < ApplicationRecord
after_commit :enqueue_confirmation, on: :create
private
def enqueue_confirmation
OrderConfirmationJob.perform_later(id)
end
endP3: Quando o Good Job superaria o Sidekiq?
O Good Job supera o Sidekiq quando o custo operacional do Redis excede seus benefícios de throughput. Para aplicações que processam menos de 50.000 jobs por dia, filas baseadas em PostgreSQL evitam a complexidade de infraestrutura, monitoramento e failover de um cluster Redis separado. O Good Job também fornece batches e jobs únicos sem custos de licença, o que importa para equipes que precisam dessas funcionalidades com orçamento limitado.
P4: Explicar idempotência de jobs e por que ela é importante para retries
Idempotência significa que executar o mesmo job múltiplas vezes produz o mesmo resultado que executá-lo uma vez. Jobs devem ser idempotentes porque falhas de rede, crashes de processos ou tratamento de timeouts podem causar execuções duplicadas. As técnicas incluem restrições de unicidade no banco de dados, verificar resultados existentes antes de processar e usar chaves de idempotência externas para APIs de pagamento.
# Processamento de pagamento idempotente
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
)
endP5: Como lidar com jobs que devem executar exatamente uma vez em workers distribuídos?
Locks distribuídos previnem execução concorrente. O Good Job usa advisory locks do PostgreSQL. O Sidekiq Enterprise oferece jobs únicos. Para implementação manual, usar Redis SETNX ou PostgreSQL pg_try_advisory_lock:
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
endComece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Escolhendo o backend certo para jobs em segundo plano no Rails
- Começar com Solid Queue para novos projetos Rails 8 que ainda não têm Redis no stack
- Migrar para Sidekiq quando o volume de jobs exceder 50.000 por dia ou quando latência de recuperação inferior a 100ms for importante
- Escolher Good Job para deploys somente PostgreSQL que precisem de batches, jobs únicos ou agendamento cron sem custos de licença
- Usar callbacks
after_commitao enfileirar jobs com Sidekiq para evitar jobs órfãos em caso de rollback de transação - Tornar cada job idempotente porque retries e processamento distribuído podem causar execuções duplicadas
- Para entrevistas, demonstrar compreensão de enfileiramento transacional de jobs, estratégias de retry e padrões de locking distribuído
Você saberia encontrar o bug em Ruby on Rails?
Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Escrito por
Anthony Fillion-MailletFundador da SharpSkill
Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.
Atualizado em 12 de setembro de 2026
Tags
Compartilhar
Artigos relacionados

Service Objects no Rails em 2026: Design Patterns, PORO e Perguntas de Entrevista Técnica
Os service objects do Rails extraem a lógica de negócio de controllers e models para classes Ruby simples. Este guia cobre padrões de projeto, implementações PORO e as perguntas de entrevista técnica mais frequentes.

API GraphQL com Rails em 2026: graphql-ruby, Subscriptions e Perguntas de Entrevista
Construir uma API GraphQL pronta para producao com Rails 8 e graphql-ruby. Design de schema, mutations, subscriptions com ActionCable e preparacao para entrevistas.

Rails Active Storage em 2026: Upload de arquivos, integração com S3 e perguntas de entrevista
Guia completo sobre Rails Active Storage em 2026: configuração de upload de arquivos, integração com AWS S3, variantes de imagens e perguntas técnicas para preparar entrevistas de Ruby on Rails.