Skip to content
Trio Solid do Rails ou a Stack Clássica? Solid Queue, Cache e Cable vs Sidekiq, Redis e AnyCable em 2026

Trio Solid do Rails ou a Stack Clássica? Solid Queue, Cache e Cable vs Sidekiq, Redis e AnyCable em 2026

TL;DR

Fique com o trio Solid em apps Rails novos em um ou poucos servidores: o Solid Queue agora tem batches, workers com fibers e tarefas recorrentes dinâmicas. Troque por componente quando os números pedirem: Sidekiq para throughput alto e sustentado, Redis para contadores atômicos, AnyCable para milhares de WebSockets.

O Rails 8 vem com Solid Queue, Solid Cache e Solid Cable por padrão, mas muitos times ainda recorrem a Sidekiq, Redis e AnyCable. Este post compara cada par com versões e funcionalidades de outubro de 2026 e traz uma tabela de decisão por componente.

Publicado em 13 min de leitura

Também disponível em English

Compartilhar

Todo app Rails 8 nasce com as mesmas três gems no Gemfile: Solid Queue para jobs, Solid Cache para o Rails.cache e Solid Cable para o Action Cable. As três guardam seus dados em um banco SQL. E todo time que já colocou Rails em produção por alguns anos tem um reflexo que diz: jobs vão no Sidekiq, cache vai no Redis ou Memcached, e WebSockets passam pelo Redis ou pelo AnyCable.

Os dois lados têm razão em alguma coisa. Este post compara cada componente Solid com a biblioteca que ele substitui, com versões e funcionalidades como estão em outubro de 2026, e termina com uma tabela de decisão que você aplica componente por componente.

O veredito primeiro

Para um app novo em um ou poucos servidores, fique com o trio Solid. Ele tira um serviço com estado da sua stack, e em 2026 as lacunas de funcionalidade que antes justificavam o Sidekiq estão praticamente fechadas. Recorra às ferramentas clássicas por componente, quando aparecer uma necessidade medida: Sidekiq para throughput de jobs alto e sustentado ou para os recursos pagos, Redis para contadores atômicos e chaves quentes abaixo do milissegundo, AnyCable para milhares de conexões WebSocket simultâneas.

A palavra importante é por componente. São três escolhas independentes, e as melhores configurações de produção muitas vezes misturam as duas abordagens.

O que você está comparando de fato

ResponsabilidadePadrão SolidEscolha clássica
Jobs em backgroundSolid Queue 1.7.0 (ago 2026)Sidekiq 8.1.7 (ago 2026)
Rails.cacheSolid Cache 1.0.10 (nov 2025)Redis ou Memcached
Pub/sub do Action CableSolid Cable 4.1.0 (set 2026)Adapter Redis ou AnyCable
ArmazenamentoSeu banco SQL (Postgres, MySQL, SQLite)RAM em um processo separado
LicençaMITSidekiq LGPL mais planos comerciais, Redis 8 AGPLv3 ou Valkey BSD

Todas as versões são as mais recentes no RubyGems no momento em que escrevo, e o próprio Rails está no 8.1.4.

A troca real: um serviço a menos contra uma ferramenta especializada

Antes de comparar funcionalidades, seja honesto sobre o custo do Redis. É mais um serviço com estado para provisionar, dimensionar, fazer backup, monitorar e ter failover. A memória precisa ser dimensionada pelo pico, não pela média. E se você usa um único Redis para cache e jobs, tem um conflito de configuração: um cache quer uma política de evição como allkeys-lru, enquanto o Sidekiq precisa de noeviction para nunca descartar um job em silêncio. O Sidekiq inclusive registra um aviso quando detecta um Redis com evição. Na prática, isso significa duas instâncias de Redis, não uma.

Também existe a questão de licença. O Redis saiu da BSD em 2024, e o Redis 8 voltou com AGPLv3 em maio de 2025, ao lado das licenças source-available. O Valkey, fork da Linux Foundation, continua BSD e é o que a maioria dos provedores de nuvem oferece hoje. Nada disso impede você, mas é mais uma decisão a tomar.

O lado Solid tem seu próprio custo: cada job, escrita de cache e broadcast vira carga SQL. A instalação padrão coloca cada componente em um banco próprio (queue, cache, cable), que você pode apontar para o mesmo servidor ou para outro. Essa separação é o que torna seguro começar em uma máquina e dividir depois.

Jobs: Solid Queue vs Sidekiq

Como funcionam

O Sidekiq empurra os payloads dos jobs para listas no Redis, e seus processadores buscam esses jobs com leituras bloqueantes na RAM. Um job custa algumas operações no Redis e quase nada além disso.

O Solid Queue guarda jobs como linhas. Os workers fazem polling em solid_queue_ready_executions com SELECT ... FOR UPDATE SKIP LOCKED, o que permite que vários workers reivindiquem linhas diferentes sem esperar pelos locks uns dos outros. O ciclo de vida de um job passa por várias tabelas (a linha do job, as execuções ready e claimed, e a atualização final), então cada job são algumas escritas indexadas. Os padrões são 3 threads por worker, intervalo de polling de 0,1 segundo para workers e de 1 segundo para o dispatcher. Ele precisa de MySQL 8+, MariaDB 10.6+ ou PostgreSQL 9.5+ para o SKIP LOCKED, e também roda em SQLite para apps menores.

Paridade de funcionalidades em 2026

A lacuna que antes encerrava essa discussão praticamente sumiu:

  • Jobs recorrentes: nativos via config/recurring.yml, e desde a 1.4.0 (março de 2026) você também pode agendá-los em tempo de execução com SolidQueue.schedule_recurring_task.
  • Controles de concorrência: limits_concurrency com uma chave, um limite e :block ou :discard em caso de conflito. O discard entrega uma versão prática de jobs únicos.
  • Batches: lançados na 1.7.0 em 21 de agosto de 2026, com callbacks on_finish, on_success e on_failure e contadores de progresso.
  • Workers com fibers: adicionados na 1.6.0 (julho de 2026). Um worker pode rodar jobs como fibers em uma única thread de reactor usando Async, o que combina com trabalho limitado por I/O, como chamadas a LLMs.
  • Dashboard: o Mission Control Jobs dá uma interface para inspecionar, refazer e descartar jobs com falha.
  • Validação de configuração: bin/jobs check (1.5.0) valida queue.yml e recurring.yml no CI ou antes de um deploy.

O plano open source do Sidekiq tem jobs agendados, retries, a Web UI e jobs iteráveis de longa duração. Batches, fetch confiável aprimorado e jobs com expiração ficam no Pro, a US$ 99/mês ou US$ 995/ano. Rate limiting, cron jobs, jobs únicos, rolling restarts e criptografia ficam no Enterprise, que começa em US$ 269/mês a cada 100 threads.

Um config/queue.yml sensato, com um worker de fibers para uma fila pesada em LLM, fica assim:

production:
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: [ critical, default ]
      threads: 5
      processes: 2
      polling_interval: 0.1
    - queues: [ llm ]
      fibers: 50
      polling_interval: 0.1

Workers com fibers exigem config.active_support.isolation_level = :fiber, que vale para o processo inteiro. Se você roda o Solid Queue dentro do Puma, suas requisições web também passam a usar isolamento por fiber, então faça isso de forma deliberada. Para mais sobre chamadas a LLMs no Rails, o guia de RubyLLM cobre o lado do cliente.

Batches ficam assim:

SolidQueue::Batch.enqueue(
  on_success: ImportFinishedJob,
  on_failure: ImportFailedJob,
  description: "CSV import #{import.id}"
) do
  import.rows.find_each { |row| ImportRowJob.perform_later(row) }
end

E um limite de concorrência que impede duas sincronizações da mesma conta de se sobreporem:

class SyncAccountJob < ApplicationJob
  limits_concurrency to: 1, key: ->(account) { account }, duration: 10.minutes

  def perform(account)
    account.sync!
  end
end

As pegadinhas que mordem em produção

Retries não são automáticos. O Solid Queue depende totalmente do Active Job. Uma exceção não tratada vira uma execução com falha e fica lá até você refazer ou descartar. O Sidekiq, ao contrário, refaz um job com falha 25 vezes ao longo de cerca de três semanas por padrão. Se você está saindo do Sidekiq, adicione retry_on ao ApplicationJob de propósito, porque o padrão do Active Job é 5 tentativas com espera de 3 segundos.

class ApplicationJob < ActiveJob::Base
  retry_on StandardError, wait: :polynomially_longer, attempts: 10
  discard_on ActiveJob::DeserializationError
end

Processos mortos também não refazem. Se um worker recebe SIGKILL, por exemplo do OOM killer, os jobs em andamento são marcados como falha com ProcessPrunedError quando o heartbeat expira (5 minutos por padrão). O retry_on não captura isso, porque o erro é registrado por outro processo. A recuperação é pelo Mission Control ou assinando o evento fail_many_claimed.solid_queue.

O nome das filas afeta a performance. Nomes exatos de fila usam um índice de cobertura. Curingas como back* ou filas pausadas forçam uma consulta DISTINCT extra a cada polling. Prefira [ background, backend ] a back*.

Controles de concorrência não são de graça. Cada job controlado cria linhas de semáforo e de execução bloqueada. Para throttling com limite bem acima de 1, uma fila dedicada com menos threads sai mais barato.

MySQL pede READ COMMITTED. Com o REPEATABLE READ padrão, os gap locks do InnoDB podem gerar deadlocks entre enfileiramentos e claims sob carga alta. Configure isso só na conexão da fila.

O plugin do Puma bloqueia phased restarts. Ele exige preload da aplicação. Tudo bem em uma única VPS, e é um motivo para rodar bin/jobs como um role separado quando você escalar.

Quando o Sidekiq ainda vence

Escolha o Sidekiq quando o throughput de jobs for alto e sustentado o bastante para a carga de escrita no banco da fila virar um custo real, quando latência de coleta abaixo de 10ms importar, quando você já opera Redis bem, ou quando quiser rate limiting e jobs únicos do Enterprise sem escrevê-los. Minha regra de bolso: centenas de jobs por segundo em um Postgres bem dimensionado são confortáveis para o Solid Queue, e milhares por segundo de forma sustentada é onde o Sidekiq se paga. Meça a sua carga antes de confiar nessa linha.

Mais um custo de migração para pesar: o Solid Queue só fala Active Job. Se o seu código usa include Sidekiq::Job e perform_async diretamente, migrar significa reescrever esses jobs, não só trocar o adapter.

Cache: Solid Cache vs Redis ou Memcached

O Solid Cache inverte a premissa de sempre. Em vez de um cache pequeno em RAM, ele mantém um cache grande em SSD, apostando que uma taxa de acerto bem maior compensa uma leitura um pouco mais lenta. Uma leitura de cache em um banco local sobre SSD é mais lenta que no Redis, mas ainda muito mais barata que a query ou o render que ela substitui, e um cache do tamanho do disco raramente descarta a entrada de que você precisa.

Como ele se comporta:

  • Evição FIFO, não LRU. Ele apaga a partir da ponta mais antiga da tabela, o que mantém barata a estimativa de tamanho e evita fragmentação.
  • max_age tem padrão de 2 semanas, e max_size ou max_entries limitam o tamanho quando configurados.
  • Sharding entre vários bancos usando hashing consistente Maglev.
  • Criptografia dos valores via Active Record Encryption, útil quando fragmentos em cache incluem dados pessoais.

Onde o Redis continua sendo a ferramenta certa: contadores atômicos e rate limiters (INCR com expiração), chaves quentes abaixo do milissegundo lidas milhares de vezes por segundo, um cache compartilhado com serviços que não são Ruby, e casos em que a semântica LRU importa. Nada impede você de usar os dois: Solid Cache atrás do Rails.cache para fragmentos e resultados de queries, e um Redis pequeno para os contadores. O post das sete camadas de cache mostra onde cada store entra no caminho da requisição.

# config/environments/production.rb
config.cache_store = :solid_cache_store

# config/initializers/redis.rb, only for counters and rate limits
REDIS = ConnectionPool.new(size: 5) { Redis.new(url: ENV.fetch("REDIS_URL")) }

Cable: Solid Cable vs Redis vs AnyCable

O Solid Cable grava cada broadcast em uma tabela e faz polling por mensagens novas, a cada 0,1 segundo por padrão, apagando mensagens mais antigas que message_retention (1 dia por padrão). A versão 4.1.0 é a atual, e os payloads podem ser criptografados.

Os benchmarks do próprio projeto, rodados em uma Hetzner CCX13, são os números mais úteis para olhar. Com 250 usuários virtuais, o Solid Cable em SQLite teve média de cerca de 146ms de ida e volta, contra cerca de 69ms do Redis. Baixar o intervalo de polling para 0,01 segundo levou o SQLite para cerca de 84ms. Com 750 usuários virtuais a diferença aumenta: cerca de 822ms no MySQL contra cerca de 163ms no Redis. Para Turbo Streams em um app típico, onde algumas centenas de usuários veem uma lista atualizar, isso está ótimo. Para um chat ou um dashboard ao vivo com muito tráfego simultâneo, não está.

Há outras duas opções que vale conhecer. Quem usa Postgres tem o adapter postgresql nativo do Action Cable, que usa LISTEN/NOTIFY e tem benchmark próximo ao do Redis, mas os payloads ficam limitados a 8KB. E quando você precisa de milhares de conexões simultâneas, garantias de entrega ou presença, o AnyCable leva o tratamento de WebSockets para um servidor separado e mantém os seus channels do Rails. Ele tem edições open source, Pro e gerenciada.

# config/cable.yml
production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds
  message_retention: 1.day

A tabela de decisão

Sua situaçãoJobsCacheCable
App novo, uma VPS, PostgresSolid QueueSolid CacheSolid Cable
Já roda Sidekiq em um Redis saudávelMantenha o SidekiqSolid CacheAdapter Redis
Milhares de jobs por segundo, baixa latênciaSidekiqQualquer umQualquer um
Precisa de rate limit ou jobs únicos prontosSidekiq Enterprise, ou Solid Queue com :discardQualquer umQualquer um
Jobs limitados por I/O, como chamadas a LLMFibers do Solid Queue ou SidekiqQualquer umQualquer um
Cache grande, taxa de acerto é o que mais importaQualquer umSolid CacheQualquer um
Contadores atômicos, leituras abaixo do milissegundoQualquer umRedis ao ladoQualquer um
Algumas centenas de usuários ao vivo simultâneosQualquer umQualquer umSolid Cable
Milhares de sockets, garantias de entregaQualquer umQualquer umAnyCable

Saindo do Sidekiq sem big bang

O Solid Queue aceita adoção incremental. Deixe o adapter global no Sidekiq e mova os jobs um a um:

class ReportJob < ApplicationJob
  self.queue_adapter = :solid_queue
end

Uma ordem segura: comece pelos jobs de baixo risco, adicione retry_on antes de mover qualquer coisa que dependia dos retries padrão do Sidekiq, porte os jobs recorrentes da sua gem de cron para o recurring.yml, e só então troque o adapter global, quando as filas do Sidekiq esvaziarem. Mantenha o Redis rodando até os conjuntos de retry e dead na Web UI do Sidekiq ficarem vazios.

Rodando com Kamal

Em um único servidor, o padrão do Rails 8 de SOLID_QUEUE_IN_PUMA: true basta: um container atende a web e roda os jobs. Quando os jobs começarem a disputar CPU com as requisições, separe-os em um role próprio:

# config/deploy.yml
servers:
  web:
    - 203.0.113.10
  job:
    hosts:
      - 203.0.113.10
    cmd: bin/jobs

O guia de deploy com Kamal 2 cobre o resto da configuração, e no desenvolvimento local uma linha jobs: bin/jobs no seu Procfile faz o mesmo papel. O post sobre Foreman ou Docker Compose mostra as duas opções.

Conclusão

O trio Solid deixou de ser a opção "boa o bastante para apps pequenos". Com batches, workers com fibers e tarefas recorrentes dinâmicas no Solid Queue, um Solid Cache do tamanho do disco e um Solid Cable que dá conta do tráfego típico de Turbo, ele é um padrão razoável para a maioria dos apps Rails em 2026. A stack clássica ainda vence nas pontas: throughput extremo de jobs, contadores abaixo do milissegundo e grandes frotas de WebSockets. Comece com Solid, acompanhe a carga de escrita no banco da fila, a taxa de acerto do cache e a latência dos broadcasts, e troque um componente por vez quando os números pedirem.

Fontes

  1. rails/solid_queue github.com
  2. rails/solid_queue releases (1.4.0 to 1.7.0) github.com
  3. rails/solid_cache github.com
  4. rails/solid_cable (README and benchmarks) github.com
  5. rails/mission_control-jobs github.com
  6. Sidekiq: OSS, Pro and Enterprise sidekiq.org
  7. Sidekiq Changes.md github.com
  8. AnyCable documentation docs.anycable.io
  9. The New Stack: Redis is open source again thenewstack.io
  10. RubyGems: rails 8.1.4 rubygems.org

Perguntas frequentes

Um app Rails 8 novo deve usar Solid Queue ou Sidekiq?

Solid Queue, a menos que você já saiba que precisa de throughput alto e sustentado ou de recursos do Sidekiq Enterprise. Ele tira o Redis da stack e, desde a 1.7.0, tem batches além de controles de concorrência e tarefas recorrentes.

O Solid Queue refaz jobs com falha automaticamente?

Não. Ele depende do Active Job, cujo padrão do retry_on é 5 tentativas com espera de 3 segundos. Adicione retry_on ao ApplicationJob de forma explícita, principalmente ao sair do Sidekiq, que refaz 25 vezes por padrão.

O Solid Cache é mais lento que o Redis?

Cada leitura é mais lenta que a RAM, mas o Solid Cache mantém um cache bem maior em SSD, então a taxa de acerto costuma ser maior. Mantenha o Redis para contadores atômicos, rate limits e chaves quentes abaixo do milissegundo.

Quando o Solid Cable não basta?

Quando há muitas conexões simultâneas ou tráfego sensível a latência, como chat. Os benchmarks do próprio projeto mostram ida e volta de cerca de 146ms com 250 usuários em SQLite contra cerca de 69ms no Redis. O AnyCable é o próximo passo para milhares de sockets.

Posso misturar componentes Solid com Sidekiq ou Redis?

Sim. As escolhas são independentes: Sidekiq para jobs com Solid Cache e Solid Cable é uma configuração comum, e o Solid Queue pode ser adotado um job por vez com self.queue_adapter.

As gems Solid precisam de bancos separados?

A instalação padrão usa bancos separados para queue, cache e cable, que podem ficar no mesmo servidor. Um banco único é suportado copiando o schema para migrations normais.

Comentários

Faça login com GitHub para comentar.

Ainda não há comentários.