Jobs en segundo plano en Rails 2026: Sidekiq vs Good Job y preguntas de entrevista
Comparación completa entre Sidekiq, Good Job y Solid Queue para tareas asíncronas en Rails, con las preguntas técnicas más frecuentes en entrevistas.

Los jobs en segundo plano en Rails han evolucionado significativamente con Rails 8.x y la introducción de Solid Queue como backend predeterminado de Active Job. La elección entre Sidekiq, Good Job y Solid Queue depende de los requisitos de rendimiento, las restricciones de infraestructura y las funcionalidades que cada proyecto necesita.
Para nuevos proyectos Rails 8, se recomienda comenzar con Solid Queue. Sidekiq es la opción adecuada para cargas de trabajo de alto rendimiento que superan los 100,000 jobs por día o cuando la latencia a nivel de Redis es crítica. Good Job es ideal para jobs respaldados por PostgreSQL con soporte nativo de batches y restricciones de unicidad.
Cómo Active Job unifica el procesamiento en segundo plano
Active Job proporciona una interfaz estandarizada para declarar, encolar y ejecutar trabajo en segundo plano en Rails. El framework abstrae las diferencias entre los backends de cola, permitiendo que el código sea portable entre Sidekiq, Good Job, Solid Queue o cualquier otro 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
endLos callbacks retry_on y discard_on manejan fallos transitorios y errores permanentes sin código específico del backend. La directiva queue_as asigna prioridad, que cada backend interpreta según su propia estrategia de procesamiento de colas.
Sidekiq 8.x: rendimiento respaldado por Redis
Sidekiq sigue siendo la referencia de rendimiento para jobs en segundo plano en Rails. La serie 8.x requiere Ruby 3.2+, Rails 7.0+ y Redis 7.2+ (Valkey y Dragonfly funcionan como reemplazos directos desde que Redis cambió su licencia).
# 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') }
endSidekiq 8 introdujo tres cambios principales: una interfaz Web reescrita desde cero que reduce el CSS de 160KB a 16KB y el tiempo promedio de renderizado de 55ms a 3ms, perfilado de jobs con Vernier accesible desde una nueva pestaña Profiles, y retención de métricas hasta por 72 horas.
Cuándo elegir Sidekiq
Sidekiq es apropiado para cargas de trabajo donde el rendimiento sostenido, la latencia de recuperación de jobs inferior al milisegundo, o las características empresariales como limitación de tasa y jobs únicos justifican ejecutar Redis. Las Capsules, introducidas en la versión 7.0 y ahora estándar, permiten que un proceso Sidekiq ejecute múltiples pools de hilos aislados con su propia concurrencia y colas.
# config/sidekiq.yml
:concurrency: 10
:queues:
- [critical, 3]
- [default, 2]
- [low, 1]
# Capsules para procesamiento aislado
:capsules:
imports:
:concurrency: 2
:queues:
- importsLa API de embedding también permite ejecutar Sidekiq dentro del proceso Puma para aplicaciones pequeñas, similar a cómo funciona el plugin Puma de Solid Queue.
¿Listo para aprobar tus entrevistas de Ruby on Rails?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Good Job 4.x: batches y unicidad nativas con PostgreSQL
Good Job utiliza LISTEN/NOTIFY de PostgreSQL para la recuperación de jobs y bloqueos advisory para garantizar ejecución única. La versión 4.19.x (actual en septiembre 2026) soporta Rails 6.1+ y 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
endGood Job incluye batches y jobs únicos en la versión open-source, funcionalidades que Sidekiq reserva para licencias de pago. La llamada perform_later inserta una fila en la tabla good_jobs dentro de la misma transacción de base de datos que el código llamante, por lo que si la transacción se revierte, el job nunca se crea.
Batches sin licencia
# 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
# Encolar el batch
GoodJob::Batch.enqueue do |batch|
BatchImportJob.perform_later(batch, file_ids: [1, 2, 3])
endJobs únicos para idempotencia
# 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
endLa restricción perform_limit: 1 asegura que solo se ejecute una sincronización por almacén en cualquier momento, previniendo trabajo duplicado cuando el mismo job se encola múltiples veces.
Solid Queue: el predeterminado de Rails 8
Solid Queue almacena jobs en la base de datos de la aplicación usando FOR UPDATE SKIP LOCKED, una característica de PostgreSQL y MySQL que convierte una tabla regular en una cola de jobs. Las nuevas aplicaciones Rails 8 vienen con Solid Queue configurado por defecto.
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
polling_interval: 0.1Solid Queue puede ejecutarse dentro del proceso del servidor web Puma con SOLID_QUEUE_IN_PUMA=true, lo que simplifica el despliegue para aplicaciones que no necesitan procesos worker dedicados. Los jobs persisten en las tablas de la base de datos, sobreviviendo a reinicios de procesos y despliegues sin dependencias externas.
Tabla comparativa de funcionalidades
| Funcionalidad | Sidekiq 8.x | Good Job 4.x | Solid Queue 1.x |
|---|---|---|---|
| Backend | Redis 7.2+ | PostgreSQL | PostgreSQL/MySQL/SQLite |
| Batches | Pro/Enterprise | Incluido | Planificado |
| Jobs únicos | Enterprise | Incluido | Manual via bloqueos |
| Programación cron | Enterprise | Incluido | Via solid_queue_cron |
| Interfaz Web | Incluida | Incluida | Mínima (Mission Control) |
| Techo de rendimiento | 100k+ jobs/min | 10k jobs/min | 10k jobs/min |
| Embeber en Puma | Sí (8.x) | No | Sí |
| Licencia | LGPL + Comercial | MIT | MIT |
Preguntas de entrevista sobre jobs en segundo plano en Rails
Las entrevistas técnicas frecuentemente evalúan la comprensión de la confiabilidad de jobs, estrategias de retry y decisiones arquitectónicas. A continuación se presentan preguntas que distinguen a los candidatos experimentados.
P1: ¿Cuál es la diferencia entre retry_on y la lógica de retry específica del backend?
retry_on es un callback de Active Job que funciona con todos los backends. Captura excepciones específicas, aplica una estrategia de espera (:polynomially_longer realiza backoff exponencial) y vuelve a encolar el job. La lógica de retry específica del backend, como sidekiq_retry_in de Sidekiq, solo funciona con ese backend y puede sobrescribir el comportamiento de Active Job.
# Retry de Active Job (portable)
class ApiSyncJob < ApplicationJob
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 8
def perform(record_id)
ExternalApi.sync(record_id)
end
endP2: ¿Qué sucede con un job si la transacción de base de datos que lo encoló se revierte?
Con colas respaldadas por base de datos (Good Job, Solid Queue), la fila del job es parte de la transacción, por lo que se revierte junto con todo lo demás. Con colas respaldadas por Redis (Sidekiq), el job ya está en Redis antes de que la transacción se complete, creando jobs huérfanos. La solución es usar callbacks after_commit:
# Patrón correcto para Sidekiq
class Order < ApplicationRecord
after_commit :enqueue_confirmation, on: :create
private
def enqueue_confirmation
OrderConfirmationJob.perform_later(id)
end
endP3: ¿Cuándo Good Job superaría a Sidekiq?
Good Job supera a Sidekiq cuando el costo operacional de Redis excede sus beneficios de rendimiento. Para aplicaciones que procesan menos de 50,000 jobs por día, las colas respaldadas por PostgreSQL evitan la complejidad de infraestructura, monitoreo y failover de un cluster Redis separado. Good Job también proporciona batches y jobs únicos sin costos de licencia, lo cual importa para equipos que necesitan estas funcionalidades con presupuesto limitado.
P4: Explicar la idempotencia de jobs y por qué es importante para los retries
Idempotencia significa que ejecutar el mismo job múltiples veces produce el mismo resultado que ejecutarlo una vez. Los jobs deben ser idempotentes porque las fallas de red, crashes de procesos o manejo de timeouts pueden causar ejecuciones duplicadas. Las técnicas incluyen restricciones de unicidad en la base de datos, verificar resultados existentes antes de procesar y usar claves de idempotencia externas para APIs de pago.
# Procesamiento de pago 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: ¿Cómo manejar jobs que deben ejecutarse exactamente una vez en workers distribuidos?
Los bloqueos distribuidos previenen la ejecución concurrente. Good Job usa bloqueos advisory de PostgreSQL. Sidekiq Enterprise ofrece jobs únicos. Para implementación manual, usar Redis SETNX o 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
end¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Elegir el backend correcto para jobs en segundo plano en Rails
- Comenzar con Solid Queue para nuevos proyectos Rails 8 que aún no tienen Redis en el stack
- Cambiar a Sidekiq cuando el volumen de jobs exceda 50,000 por día o cuando la latencia de recuperación inferior a 100ms sea importante
- Elegir Good Job para despliegues solo PostgreSQL que necesiten batches, jobs únicos o programación cron sin costos de licencia
- Usar callbacks
after_commital encolar jobs con Sidekiq para evitar jobs huérfanos en caso de rollback de transacción - Hacer cada job idempotente porque los retries y el procesamiento distribuido pueden causar ejecuciones duplicadas
- Para entrevistas, demostrar comprensión del encolado transaccional de jobs, estrategias de retry y patrones de bloqueo distribuido
¿Sabrías detectar el bug en Ruby on Rails?
Un fragmento real, un bug oculto, un intento al día. Sin cuenta para probar.

Escrito por
Anthony Fillion-MailletFundador de SharpSkill
Desarrollador fullstack desde hace más de 10 años. Dirige SharpSkill y responde por todo lo que se publica aquí.
Actualizado el 12 de septiembre de 2026
Etiquetas
Compartir
Artículos relacionados

Service Objects en Rails 2026: Design Patterns, PORO y Preguntas de Entrevista Técnica
Los service objects de Rails extraen la lógica de negocio de controladores y modelos hacia clases Ruby simples. Esta guía cubre patrones de diseño, implementaciones PORO y las preguntas de entrevista técnica más frecuentes.

API GraphQL con Rails en 2026: graphql-ruby, Subscriptions y Preguntas de Entrevista
Construir una API GraphQL lista para produccion con Rails 8 y graphql-ruby. Diseno de esquema, mutaciones, subscriptions con ActionCable y preparacion para entrevistas.

Rails Active Storage en 2026: Subida de archivos, integración con S3 y preguntas de entrevista
Guía completa sobre Rails Active Storage en 2026: configuración de subida de archivos, integración con AWS S3, variantes de imágenes y preguntas técnicas para preparar entrevistas de Ruby on Rails.