16 puntos por GN⁺ 2026-01-15 | 2 comentarios | Compartir por WhatsApp
  • Rails 8 elimina la dependencia de Redis de su stack por defecto y cambia a procesar todo el trabajo sobre una base de datos relacional (RDB) mediante SolidQueue, SolidCache y SolidCable
  • Redis es rápido y estable, pero también introduce complejidad operativa en configuración, seguridad, gestión de clústeres, respaldos, etc.
  • SolidQueue usa la función FOR UPDATE SKIP LOCKED de PostgreSQL para implementar procesamiento paralelo sin contención
  • Ofrece gratis funciones de Redis + Sidekiq de pago, como trabajos periódicos, control de concurrencia y panel de monitoreo (Mission Control)
  • Para la mayoría de las aplicaciones Rails, SolidQueue es suficiente, y solo en algunos casos que requieren procesamiento ultrarrápido o en tiempo real conviene mantener Redis

El costo oculto de Redis

  • Además del simple costo de hosting, Redis implica una carga continua de administración, como instalación, mantenimiento, configuración de seguridad y gestión de clústeres HA
    • Se necesita conexión de red y configuración de firewall entre Rails y Redis, autenticación del cliente y orquestación de procesos de Sidekiq
  • Cuando ocurre una falla, hay que depurar al mismo tiempo Redis y el RDBMS, y también se requiere una estrategia de respaldos duplicada
  • En cambio, con un stack Rails sin Redis, se puede simplificar la operación administrando solo PostgreSQL

Cómo funciona SolidQueue

  • Usa FOR UPDATE SKIP LOCKED de PostgreSQL para que varios workers tomen trabajos al mismo tiempo sin conflictos de bloqueo (lock contention)
  • Estructura principal de tablas
    1. solid_queue_jobs: almacena los metadatos de los trabajos
    2. solid_queue_scheduled_executions: espera de trabajos programados
    3. solid_queue_ready_executions: cola de trabajos listos para ejecutar
  • Los procesos de worker, dispatcher, scheduler y supervisor hacen polling periódico sobre distintas tablas y colaboran entre sí
  • Gracias al diseño MVCC y al autovacuum de PostgreSQL, puede manejar de forma estable grandes volúmenes de inserciones y eliminaciones

Programación de tareas repetitivas

  • SolidQueue incluye por defecto trabajos recurrentes estilo cron, configurados en el archivo config/recurring.yml
  • El scheduler pone en cola los trabajos cuando llega su hora de ejecución y programa automáticamente la siguiente ejecución
  • Usa la librería Fugit para interpretar horarios en lenguaje natural y Concurrent::ScheduledTask para crear hilos
  • Adopta el enfoque de programación determinista de GoodJob, para mantener el calendario incluso tras reinicios del proceso

Función de control de concurrencia

  • SolidQueue usa el patrón de semáforo POSIX para admitir límites de ejecución concurrente por unidad de trabajo
    • Ejemplo: con limits_concurrency to: 1, key: ->(user) { user.id }, solo se ejecuta 1 trabajo por usuario
  • Se puede definir el vencimiento del semáforo (duration) para evitar conflictos y deadlocks
  • Tablas relacionadas
    • solid_queue_semaphores: seguimiento de límites de concurrencia
    • solid_queue_blocked_executions: almacena trabajos en espera

Monitoreo con Mission Control

  • Mission Control Jobs es un panel gratuito y open source para Rails 8, que puede montarse fácilmente en la ruta /jobs
  • Funciones principales
    • Estado de colas en tiempo real, seguimiento de trabajos fallidos y control de reintentos/descartes
    • Visualización de la línea de tiempo de trabajos programados y recurrentes
    • Gráficas de throughput y métricas por cola
  • Permite consultas basadas en SQL, por lo que se puede analizar directamente en la base de datos sin herramientas adicionales

Migración de Sidekiq a SolidQueue

  • Paso 1: configurar config.active_job.queue_adapter = :solid_queue
  • Paso 2: ejecutar bundle add solid_queue, luego rails solid_queue:install y db:migrate
  • Paso 3: convertir el cron schedule de sidekiq.yml a recurring.yml
  • Paso 4: agregar jobs: bundle exec rake solid_queue:start al Procfile
  • Paso 5: eliminar los gems relacionados con Redis y Sidekiq
  • El código existente de ActiveJob sigue funcionando sin cambios

Casos en los que Redis sigue siendo necesario

  • Procesamiento sostenido de miles de trabajos por segundo
  • Sistemas en tiempo real donde la latencia menor a 1 ms es indispensable
  • Necesidad de estructuras pub/sub complejas o de rate limiting y operaciones de contador sofisticadas
  • Como ejemplo, Shopify opera con 833 solicitudes por segundo y 1,172 procesos worker usando infraestructura Redis

Guía de implementación real

  • Al crear una nueva app en Rails 8, SolidQueue, SolidCache y SolidCable se configuran automáticamente
  • Se recomienda definir una conexión de base de datos separada para la cola en config/database.yml
  • Agregar autenticación a Mission Control y montar la ruta /jobs
  • Agregar jobs: bundle exec rake solid_queue:start a Procfile.dev y ejecutar todo con bin/dev
  • Tras crear trabajos de prueba, se puede verificar su estado en Mission Control

Problemas frecuentes y soluciones

  • También se puede usar una configuración de base de datos única, pero con menos flexibilidad operativa
  • En Mission Control en producción, es indispensable agregar autenticación
  • El valor por defecto del intervalo de polling es 1 segundo para trabajos programados y 0.2 segundos para trabajos inmediatos, adecuado para la mayoría de las apps
  • Si se usa ActionCable/Turbo Streams, hay que configurar SolidCable con una conexión de base de datos separada

Escalabilidad y rendimiento

  • SolidQueue puede escalar lo suficiente para la mayoría de las apps Rails
  • Basado en PostgreSQL, permite procesar 200–300 trabajos por segundo, y 37signals procesa 20 millones de trabajos al día sin Redis
  • Tabla comparativa
    Ítem Redis + Sidekiq SolidQueue
    Complejidad de configuración Requiere servicio aparte Usa DB integrada
    Lenguaje de consulta Comandos de Redis SQL
    Monitoreo Panel aparte Mission Control
    Escenarios de falla 6 o más 2
    Throughput Miles por segundo 200–300 por segundo
    Ideal para 99.9% de apps 95% de apps

Conclusión

  • Redis y Sidekiq son tecnologías excelentes, pero para la mayoría de las aplicaciones Rails generan una complejidad y un costo excesivos
  • SolidQueue hace posible simplificar la operación, reducir costos y mejorar el mantenimiento con una base de datos única
  • En la era de Rails 8, se recomienda migrar a SolidQueue como opción predeterminada

2 comentarios

 
kaydash 2026-01-17

Redis está bueno, pero.

 
GN⁺ 2026-01-15
Opiniones en Hacker News
  • Creo que todo autor de código abierto tiene derecho a controlar el alcance de su proyecto
    Pero nuestro equipo se arrepiente de haber cambiado de good_job a SolidQueue
    Basecamp está centrado en MySQL, así que no acepta consultas específicas del motor RDBMS. Si ves los issues en GitHub, se nota que solo se enfocan en el rendimiento con MySQL
    Además, todavía no tiene soporte para trabajos por lotes (PR relacionada)

    • Suena como la peor combinación posible. Nosotros también usamos MySQL, pero no podríamos vivir sin consultas específicas del motor
      En JOINs complejos, MySQL muchas veces arma mal el plan de ejecución, así que yo fuerzo el orden con STRAIGHT_JOIN. Es una forma de cubrirse a futuro
    • Si ya estás tan atado a MySQL, ¿no sería lógico usar funciones exclusivas de MySQL? Siento que aquí falta algo
    • Me gustaría escuchar con más detalle por qué recomiendan GoodJob sobre SolidQueue
      Estoy comparando ambos como candidatos para migrar desde resque. GoodJob no es compatible con el modo transaction de pgbouncer por sus funciones exclusivas de pg
      Es molesto porque requiere persistencia de sesión, pero la mejora de rendimiento no significa mucho en la mayoría de las escalas
      Aun así, el modelo de desarrollo y la legibilidad del código de GoodJob inspiran mucha más confianza
    • De acuerdo. good_job es un enfoque ideal para una cola basada en Postgres
    • Todavía no conozco bien SolidQueue, pero good_job me ha dado muchísimo gusto usarlo. Funciona muy bien
  • Si puede simplificar el entorno de producción, siempre es algo bueno
    En Rails, creo que el escenario ideal es una arquitectura que permita cambiar fácilmente a Redis
    Estaría bien empezar con SolidQueue y, si luego aparece un límite de escalabilidad, poder migrar a Redis
    La mayoría de las apps Rails no tienen tanto tráfico, así que mantener dos sistemas más bien agrega complejidad

    • Rails ofrece una API abstraída llamada Active Job, así que cambiar a Redis es bastante fácil
      Claro, hay apps que dependen de una implementación específica de cola, pero en general basta con cambiar la configuración
    • Me pregunto si el modo AOF de Redis registra todos los cambios como un WAL
      Quisiera saber si también usa snapshots para evitar que el log crezca demasiado, y si esto funciona también en modo distribuido
    • Si dependes demasiado de las transacciones, migrar se vuelve difícil
      Sobre todo cuando la creación de trabajos ocurre junto con otros cambios en la BD, porque ahí se pierde esa garantía
    • Rails no separa el procesador de trabajos en segundo plano de la BD de producción, y eso genera confusión
      Redis tenía la ventaja de ser un almacenamiento de estado ligero e independiente en este aspecto
      SolidQueue no parece dejar clara esa separación (riverqueue.com)
  • Probé SolidQueue en mi proyecto personal
    Mi conclusión fue que, si no tienes problemas con Sidekiq, no hay razón para cambiar
    Solo vale la pena considerarlo si quieres eliminar la infraestructura de Redis
    Para un proyecto nuevo, GoodJob me parece más maduro y con mejor comunidad
    La UI de SolidQueue es demasiado básica, y eso me resultó incómodo. Como los índices no estaban optimizados, cuando crecían los datos la página se quedaba congelada
    También hay que considerar que usar un RDBMS agrega el costo de gestionar el pool de conexiones

  • Para quienes se preocupan por la escalabilidad, si miran el benchmark de Oban en Elixir,
    procesa un millón de trabajos por minuto en un solo nodo. La mayoría de las apps manejan mucho menos que eso

    • En nuestra empresa también usamos Oban, y Oban recomienda usar Redis como notifier o hacer polling (documentación de scaling)
    • Pero ese benchmark está bastante lejos de una app real
      Mete 5000 trabajos por lote de una sola vez, así que el TPS real es como de 200
      Si insertas trabajos individuales sin lotes, la carga de transacciones SQL se vuelve mucho mayor
  • Nosotros ya guardábamos los trabajos en la BD desde antes de SolidQueue
    La ventaja es que puedes hacer un snapshot del estado de producción tal cual hacia el entorno de desarrollo
    Pero dejamos el rate limiter en Redis para evitar carga extra en la BD

  • El límite de una cola basada en BD está en los payloads grandes
    Si metes JSON grandes en la cola, se vuelve ineficiente por el overhead de escritura en la BD
    Redis (Sidekiq) es mucho más rápido en esos casos
    SolidQueue+SQLite puede servir simplemente para pasar la primary key
    Pero si varios workers hacen polling sobre la misma BD, el cuello de botella aparece rápido

    • En la práctica, lo normal es pasar en los parámetros del trabajo uno o dos IDs como mucho. Más que eso ya es ineficiente
    • Redis tampoco sirve para payloads grandes por sus límites de memoria
      Creo que es mejor dejar los datos grandes en un almacenamiento externo como S3 y pasar solo la referencia
    • De todos modos, otras partes del sistema también necesitan almacenamiento, así que usar un depósito temporal como S3 o garage parece lo más realista
      Me pregunto si existe algún material que resuma resultados de benchmarks
    • La documentación de Sidekiq también recomienda pasar solo identificadores
    • Guardar payloads grandes en Redis es una mala práctica porque la memoria es limitada
  • En SolidQueue se menciona SKIP LOCKED, pero mantener una transacción abierta para un trabajo de 15 minutos es arriesgado
    Las transacciones abiertas durante mucho tiempo destruyen el rendimiento de la BD y además son vulnerables a cortes de red
    Ese tipo de estructura puede llevar a un antipatrón. Después vi que parece usar un esquema de lease

  • Me identifico con la filosofía de Postgres for everything
    Me parece bien unificar todo en PostgreSQL por simplicidad

    • A mí también me gusta la idea de ir con PG para todo, pero seguido escucho eso de “si solo tienes un martillo, todo te parece un clavo”
      No sé bien cómo rebatir esa analogía
    • Hoy en día el almacenamiento NVMe es tan rápido que siento que la ventaja de Redis se ha reducido
      Me cuesta ver por qué valdría la pena usar Redis si eso solo aumenta la complejidad
  • “Un negocio donde importa una latencia menor a 1 ms”; ¿o sea que hacen HFT con Rails?

    • Claro que no. Si ves el caso de SimpleThread, esa empresa está muy lejos del HFT
    • El motor de trading no correría en Rails, pero la UI de monitoreo de operaciones sí podría estar hecha con Rails
  • Postgres se va a comer el mundo

    • Yo también estoy de acuerdo. Tal vez algún día salga una extensión pg_kernel y hasta podamos borrar Linux
    • Pero también puede que en unos años nos demos cuenta de que “Postgres for everything” fue una moda exagerada, igual que “MongoDB for everything”
    • Aun así, MySQL es fácil de mantener y además rinde bastante bien (lo digo incluso siendo usuario de Postgres)
    • Ahora uso PGQM y PG_CRON, y todo se siente mucho más limpio que la vieja combinación de MySQL + Redis + AWS
    • Al final lo que importa es el conjunto de funcionalidades. El RDBMS se va a comer el mundo