Solid Queue y Solid Cache en Rails 8: Guía completa para entrevistas técnicas 2026
Análisis profundo de Solid Queue y Solid Cache, los componentes por defecto respaldados por base de datos en Rails 8. Batches de jobs, ejecución por fibras, Active Job Continuations y conocimientos clave para entrevistas técnicas 2026.

Solid Queue y Solid Cache representan el cambio de infraestructura más significativo en la historia de Rails. Ambos componentes se incluyen por defecto en Rails 8, reemplazando Redis para trabajos en segundo plano y almacenamiento en caché con alternativas respaldadas por base de datos que eliminan una capa completa de complejidad operacional.
Rails 8 utiliza por defecto tres componentes respaldados por base de datos: Solid Queue (trabajos en segundo plano), Solid Cache (caché) y Solid Cable (WebSockets). En conjunto, eliminan la dependencia de Redis en la mayoría de las aplicaciones Rails. Este es un tema frecuente en las entrevistas técnicas de Rails 8.
Cómo Solid Queue reemplaza los backends de jobs basados en Redis
Solid Queue es un backend de Active Job respaldado por base de datos que almacena los jobs directamente en PostgreSQL, MySQL o SQLite. El mecanismo clave es FOR UPDATE SKIP LOCKED, una característica SQL disponible en PostgreSQL 9.5+ y MySQL 8+ que convierte una tabla relacional ordinaria en una cola de trabajo concurrente sin bloqueos.
La arquitectura se compone de tres elementos:
- Workers: consultan la tabla
solid_queue_ready_executionsy reservan jobs medianteSKIP LOCKED - Dispatchers: mueven los jobs programados desde
solid_queue_scheduled_executionshacia la tabla de listos cuando llega su momento de ejecución - Schedulers: gestionan las tareas recurrentes definidas en la configuración
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
polling_interval: 0.1
processes: 2Esta configuración ejecuta dos procesos worker con 5 hilos cada uno, consultando la base de datos cada 100 ms. El dispatcher verifica los jobs programados cada segundo en lotes de 500.
Encolado transaccional en Rails 8
Uno de los argumentos más sólidos a favor de Solid Queue frente a los backends basados en Redis es el encolado transaccional. Cuando un job se encola dentro de una transacción de base de datos, solo se hace visible después del commit. Los backends de Redis no pueden ofrecer esta garantía: un job podría ejecutarse antes de que la transacción que lo creó finalice, referenciando registros que aún no existen.
# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
self.enqueue_after_transaction_commit = true
queue_as :default
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
end
end
# app/models/user.rb
class User < ApplicationRecord
after_create do
SendWelcomeEmailJob.perform_later(id)
# Job only enqueued after the CREATE transaction commits
# No risk of the job running before the user record exists
end
endCon enqueue_after_transaction_commit habilitado, el job se difiere hasta que la transacción que lo envuelve tenga éxito. Si la transacción hace rollback, el job nunca se encola. Esto elimina toda una categoría de condiciones de carrera que afectan a las colas respaldadas por Redis.
Controles de concurrencia y colas prioritarias
Solid Queue incluye controles de concurrencia nativos que Sidekiq solo ofrece en su versión Enterprise de pago. La opción concurrency_limit restringe cuántos jobs de un tipo determinado pueden ejecutarse simultáneamente.
# app/jobs/api_sync_job.rb
class ApiSyncJob < ApplicationJob
limits_concurrency to: 3, key: ->(account_id) { "api_sync_#{account_id}" }
def perform(account_id)
account = Account.find(account_id)
ExternalApi.sync(account)
end
endEsta configuración asegura que como máximo 3 jobs de sincronización API se ejecuten simultáneamente por cuenta, previniendo violaciones de límites de tasa sin coordinación externa. Los jobs bloqueados se almacenan en solid_queue_blocked_executions y se liberan automáticamente cuando un espacio queda disponible.
La prioridad funciona en dos niveles: prioridad numérica por job (número menor = prioridad más alta) y orden de colas en la configuración del worker. Ambos se pueden combinar para un control detallado del orden de ejecución.
Una pregunta habitual en entrevistas de Rails 8 se centra en las diferencias entre Solid Queue y Sidekiq. El factor diferenciador clave: Solid Queue ofrece garantías transaccionales y controles de concurrencia integrados sin costo adicional. Sidekiq supera en rendimiento bruto para cargas de alto volumen (más de 10,000 jobs/minuto) gracias al almacenamiento en memoria de Redis. Para el 95% de las aplicaciones, Solid Queue proporciona rendimiento suficiente. Consultar la comparación de jobs en segundo plano en Rails para benchmarks detallados.
Batches de jobs para operaciones agrupadas
Solid Queue 1.7.0 introdujo los batches de jobs, permitiendo agrupar y rastrear múltiples jobs como un conjunto. Esta funcionalidad permite ejecutar callbacks cuando todos los jobs de un batch terminan, un patrón que antes requería Sidekiq Pro.
# app/jobs/batch_import_job.rb
class BatchImportJob < ApplicationJob
def perform(file_id)
file = ImportFile.find(file_id)
SolidQueue::Batch.enqueue(
on_finish: BatchFinishedJob,
on_success: NotifyUserJob,
on_failure: AlertOpsJob
) do |batch|
file.rows.each_slice(100) do |rows|
ProcessRowsJob.perform_later(rows.map(&:id))
end
end
end
endEl batch rastrea todos los jobs encolados dentro de su bloque. Cuando todos los jobs terminan, on_finish se dispara independientemente del éxito o fracaso. Si todos los jobs tienen éxito, on_success se dispara. Si algún job falla, on_failure se dispara. Esto permite flujos de trabajo como el procesamiento de importaciones donde un paso final debe esperar a que todas las partes se completen.
Los jobs creados fuera de un batch pero encolados dentro de uno se unen a ese batch. Un batch que termina sin jobs finaliza inmediatamente, disparando sus callbacks de inmediato.
Modo de ejecución por fibras para cargas I/O-bound
Solid Queue 1.6.0 añadió la ejecución de workers basada en fibras usando la gema Async. Este modo ejecuta los jobs en fibras en lugar de hilos, lo cual es beneficioso para cargas de trabajo I/O-bound como llamadas a APIs de LLM donde la mayor parte del tiempo se pasa esperando respuestas.
# config/solid_queue.yml
production:
workers:
- queues: [llm_calls, external_apis]
fibers: 100
polling_interval: 0.5Con 100 fibras, 100 jobs I/O-bound concurrentes pueden ejecutarse en un solo proceso con un overhead de memoria mínimo. Esto se compara favorablemente con 100 hilos, que consumirían significativamente más memoria y enfrentarían contención en el GVL (Global VM Lock).
El modo de fibras requiere que Rails esté configurado para aislamiento por fibras:
# config/application.rb
config.active_support.isolation_level = :fiberLos jobs CPU-bound deben continuar usando hilos, ya que las fibras no proporcionan beneficio cuando el trabajo no cede el control a I/O.
Active Job Continuations en Rails 8.1
Rails 8.1 introdujo Active Job Continuations, permitiendo que los jobs de larga duración se pausan y reanuden desde puntos de control. Esto resuelve el problema de los jobs que reinician desde cero cuando son interrumpidos por despliegues o reinicios de contenedores.
# app/jobs/process_import_job.rb
class ProcessImportJob < ApplicationJob
include ActiveJob::Continuable
def perform(import_id)
@import = Import.find(import_id)
step :validate do
@import.validate!
end
step :process_records do |step|
@import.records.find_each(start: step.cursor) do |record|
record.process
step.advance!(from: record.id)
end
end
step :finalize do
@import.mark_complete!
end
end
endEl método step define etapas discretas. Si el job es interrumpido, reanuda desde la última etapa completada. Dentro de una etapa, step.cursor rastrea el progreso: step.advance!(from: record.id) guarda la posición del cursor. Al reanudar, find_each(start: step.cursor) continúa donde se detuvo el procesamiento.
Las Continuations requieren que el adaptador de cola implemente stopping?. Solid Queue soporta esto desde la v1.2.0. Delayed Job y Resque no soportan interrupción elegante sin trabajo adicional.
El cursor puede ser cualquier valor serializable. Para bucles anidados, se usa un array:
step :process_nested, start: [0, 0] do |step|
Account.find_each(start: step.cursor[0]) do |account|
account.records.find_each(start: step.cursor[1]) do |record|
record.process
step.set!([account.id, record.id + 1])
end
step.set!([account.id + 1, 0])
end
endJobs recurrentes sin cron
Solid Queue reemplaza la programación basada en cron con un scheduler integrado. Las tareas recurrentes se definen en un archivo de configuración YAML y son gestionadas por el proceso scheduler.
# config/recurring.yml
production:
cleanup_expired_sessions:
class: CleanupExpiredSessionsJob
schedule: every 6 hours
daily_report:
class: DailyReportJob
schedule: every day at 6am
queue: reports
weekly_digest:
class: WeeklyDigestJob
schedule: every Monday at 9amEl proceso scheduler lee este archivo y encola los jobs correspondientes en los intervalos definidos. A diferencia de cron, se ejecuta dentro del mismo supervisor de procesos y comparte la misma conexión a la base de datos. El soporte de zonas horarias se añadió en Solid Queue 1.5.0.
Despliegue con integración Puma
Rails 8 con Kamal proporciona despliegue sin configuración para Solid Queue. El parámetro SOLID_QUEUE_IN_PUMA=1 indica a Puma que haga fork y supervise los procesos de Solid Queue junto al servidor web.
# config/puma.rb (Rails 8 default)
plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"]Este modelo de despliegue en un solo proceso simplifica la orquestación de contenedores. Una sola imagen Docker ejecuta tanto el servidor web como los procesadores de jobs, reduciendo la sobrecarga operacional para aplicaciones pequeñas y medianas.
¿Listo para aprobar tus entrevistas de Ruby on Rails?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Solid Cache: caché respaldado por base de datos que escala
Solid Cache es un ActiveSupport::Cache::Store respaldado por base de datos que aprovecha el rendimiento de los SSD modernos para reemplazar Redis y Memcached como almacén de caché por defecto. La premisa: los SSD son solo marginalmente más lentos que la RAM para operaciones de lectura, pero ofrecen órdenes de magnitud más almacenamiento a una fracción del costo. Solid Cache está en producción en Basecamp manejando 10TB con retención de 60 días, reduciendo los tiempos de renderizado P95 a la mitad.
Solid Cache utiliza una estrategia de expiración FIFO (First In, First Out) en lugar de LRU (Least Recently Used). Aunque FIFO es teóricamente menos eficiente, la capacidad de almacenamiento vastamente superior compensa: las entradas permanecen en caché mucho más tiempo, reduciendo los cache misses en general.
# config/environments/production.rb
config.cache_store = :solid_cache_store
# config/solid_cache.yml
production:
databases:
- cache
store_options:
max_age: 604800 # 1 week in seconds
max_size: 256 # Max entry size in KB
namespace: "app_v1"
expiry_batch_size: 100 # Entries cleaned per expiry cycleArquitectura del caché y mecanismo de expiración
Solid Cache rastrea las escrituras mediante un contador interno. Cuando el contador alcanza el 50% del expiry_batch_size configurado, una tarea en segundo plano se activa para limpiar las entradas expiradas. Este enfoque amortizado evita las pausas de tipo stop-the-world que pueden ocurrir con la evicción LRU en instancias de Redis con memoria limitada.
La tabla solid_cache_entries almacena todos los datos en caché:
# db/cache_schema.rb (generated by installer)
create_table :solid_cache_entries do |t|
t.binary :key, null: false, limit: 1024
t.binary :value, null: false, limit: 262144 # 256 KB default
t.datetime :created_at, null: false
t.index :key, unique: true
t.index :created_at # For FIFO expiry
endLa lectura y escritura en esta tabla utilizan por defecto el mismo pool de conexiones que el resto de la aplicación. Para aplicaciones de alto tráfico, configurar una base de datos separada para los datos de caché evita que las operaciones de caché impacten el rendimiento de la base de datos principal.
Configuración de base de datos separada para el caché
Aislar Solid Cache en una base de datos dedicada es sencillo y recomendado para cargas de producción que generan tráfico de caché significativo.
# config/database.yml
production:
primary:
<<: *default
database: myapp_production
cache:
<<: *default
database: myapp_cache_production
migrations_paths: db/cache_migrateEsta separación asegura que millones de operaciones de escritura de caché no inflen el WAL (Write-Ahead Log) de la base de datos principal ni compitan por espacios en el pool de conexiones con las consultas de la aplicación.
Sin una base de datos separada, las lecturas y escrituras de Solid Cache participan en cualquier transacción ActiveRecord que las envuelva. Esto significa que una transacción de larga duración mantiene las entradas de caché en un estado sin commit. Es fundamental configurar una base de datos de caché dedicada para aplicaciones en producción.
Sharding y cifrado
Solid Cache soporta el sharding de datos en caché a través de múltiples bases de datos para distribuir la carga. También soporta atributos cifrados, los datos en caché permanecen cifrados en reposo, un requisito de cumplimiento para aplicaciones que manejan información sensible.
# config/solid_cache.yml
production:
databases:
- cache_shard_1
- cache_shard_2
- cache_shard_3
store_options:
max_age: 1209600 # 2 weeksLas entradas se distribuyen entre los shards usando hashing consistente sobre la clave de caché. Agregar o eliminar shards causa un aumento temporal en los cache misses mientras las entradas se redistribuyen, pero no se produce pérdida de datos.
Monitoreo con Mission Control Jobs
Mission Control Jobs proporciona un panel web para inspeccionar y gestionar los jobs de Solid Queue. Muestra los workers, las colas y los estados de los jobs (en progreso, finalizados, bloqueados, fallidos) a través de un engine Rails montado.
# config/routes.rb
Rails.application.routes.draw do
mount MissionControl::Jobs::Engine, at: "/jobs"
end
# Gemfile
gem "mission_control-jobs", ">= 1.0.1"Mission Control también expone una API de consola para operaciones masivas sobre jobs fallidos:
# Rails console
ActiveJob.jobs.failed.where(job_class: "ApiSyncJob").retry_all
ActiveJob.jobs.failed.where(job_class: "BrokenJob").discard_allEste acceso programático es esencial para manejar fallos de jobs a gran escala sin necesidad de navegar manualmente por un panel de control.
Fuentes
- Notas de la versión Rails 8.0: documentación oficial sobre Solid Queue y Solid Cache por defecto
- Releases de Solid Queue en GitHub: changelog para batches (v1.7.0), modo fibra (v1.6.0) y soporte de continuations (v1.2.0)
- PR de Active Job Continuations: detalles de implementación en Rails 8.1
- Introducing Solid Queue (37signals): razonamiento del diseño y uso en producción en HEY
Preguntas técnicas clave para entrevistas
Las entrevistas de Rails 8 se enfocan cada vez más en el stack Solid. A continuación, las preguntas que surgen con mayor frecuencia junto con la profundidad de respuesta esperada.
P: ¿Cómo logra Solid Queue procesar jobs de forma concurrente sin Redis?
Solid Queue utiliza FOR UPDATE SKIP LOCKED, una cláusula SQL que permite a múltiples workers consultar la misma tabla sin bloquearse mutuamente. Cada worker bloquea un lote de filas, las procesa y elimina los registros de ejecución. Los demás workers omiten las filas ya bloqueadas y reservan jobs diferentes.
P: ¿Qué problema resuelve el encolado transaccional?
Evita que los jobs se ejecuten antes de que la transacción de base de datos que los originó haya sido commitida. Sin esto, un job podría referenciar un registro que fue revertido mediante rollback, causando errores ActiveRecord::RecordNotFound.
P: ¿Por qué Solid Cache usa FIFO en lugar de LRU? FIFO es más simple de implementar en una base de datos y evita la amplificación de escritura al no necesitar actualizar marcas de tiempo de acceso en cada lectura. La compensación viene de la capacidad SSD: las entradas permanecen más tiempo, por lo que la tasa de aciertos se mantiene alta a pesar de la estrategia de evicción menos óptima.
P: ¿Cómo funcionan los batches de jobs en Solid Queue?
Los jobs encolados dentro de un bloque SolidQueue::Batch.enqueue se rastrean juntos. El batch dispara on_finish cuando todos los jobs terminan, on_success si todos tienen éxito, o on_failure si alguno falla. Esto permite flujos de trabajo como importaciones por lotes donde un paso final depende de que todas las partes se completen.
P: ¿Qué son las Active Job Continuations y cuándo se deben usar? Las Continuations permiten que los jobs de larga duración guarden su progreso y reanuden después de una interrupción. Se usan para jobs que procesan grandes conjuntos de datos, como importaciones o actualizaciones por lotes, donde reiniciar desde cero en cada despliegue desperdiciaría tiempo y recursos significativos.
P: ¿Cuándo debería una aplicación seguir usando Redis en lugar del stack Solid? Redis sigue siendo superior para aplicaciones que procesan más de 10,000 jobs por minuto, cargas que requieren lecturas de caché por debajo del milisegundo, o aplicaciones que ya utilizan Redis para otros propósitos (Pub/Sub, rate limiting, almacenamiento de sesiones). El stack Solid apunta a la simplicidad, no al rendimiento máximo.
Estas preguntas y muchas más se pueden practicar en los módulos ActiveJob y trabajos en segundo plano y Estrategias de caché de SharpSkill.
¿Listo para aprobar tus entrevistas de Ruby on Rails?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Qué recordar sobre Solid Queue y Solid Cache en Rails 8
- Solid Queue reemplaza las colas de jobs basadas en Redis con una solución respaldada por base de datos usando
FOR UPDATE SKIP LOCKEDpara procesamiento concurrente - El encolado transaccional elimina las condiciones de carrera entre escrituras en base de datos y ejecución de jobs, una garantía que Redis no puede proporcionar
- Los batches de jobs (v1.7.0) permiten operaciones agrupadas con callbacks de finalización, una funcionalidad que antes era exclusiva de Sidekiq Pro
- El modo de ejecución por fibras (v1.6.0) mejora el throughput para cargas I/O-bound como llamadas a APIs de LLM
- Las Active Job Continuations (Rails 8.1) permiten que los jobs de larga duración guarden su progreso y reanuden después de una interrupción
- Los controles de concurrencia integrados, jobs recurrentes e integración con Puma se incluyen en Solid Queue sin costo adicional
- Solid Cache utiliza caché FIFO respaldado por SSD con sharding y cifrado opcionales, eliminando Memcached y Redis de la pila de infraestructura
- La configuración de una base de datos separada para Solid Cache evita que las operaciones de caché impacten el rendimiento de la base de datos principal
- Mission Control Jobs proporciona monitoreo en producción y gestión masiva de jobs a través de un panel web y una API de consola
- Para la mayoría de las aplicaciones Rails 8 en 2026, el stack Solid es la opción por defecto recomendada. Redis sigue siendo la elección solo para casos de alto rendimiento que superan los 10,000 jobs por minuto
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
¿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 10 de octubre de 2026
Etiquetas
Compartir
Artículos relacionados

Ruby on Rails 8: Nuevas Características y Guía de Migración 2026
Ruby on Rails 8 presenta el Solid Trifecta, un generador de autenticación integrado, Kamal 2 y Propshaft. Este tutorial cubre cada característica principal y detalla la actualización desde Rails 7 paso a paso.

Modo API de Rails en 2026: API RESTful, serialización y buenas prácticas
Dominar el modo API de Rails con buenas prácticas de diseño RESTful, serialización JSON con Alba y jsonapi-serializer, estrategias de autenticación y manejo de errores en Rails 8.

Trabajos freelance de desarrollador Ruby on Rails en 2026: dónde encontrar contratos, tarifas diarias, preparación
El mercado freelance de Ruby on Rails en 2026: plataformas para encontrar proyectos, tarifas diarias promedio, perfiles buscados y consejos para conseguir contratos.