世界を動かす技術を、日本語で。

RedisからSolidQueueに移行します

2026年1月14日原文(simplethread.com)

概要

  • Rails 8では Redisが標準スタックから除外 され、SolidQueueなどの新機能がDBベースで動作
  • SolidQueueは PostgreSQLなどのRDBMSを利用してジョブキューを管理 し、Redis不要に
  • Redis導入・運用のコストや複雑さを削減し、 Railsアプリのシンプル化が可能
  • SolidQueueは 高機能(定期実行・同時実行制限・UI)を標準装備
  • Redisが必要なケースもあるが、 大半のアプリはSolidQueueで十分対応可能

Rails 8でRedisが不要になった理由

  • Rails 8 では、 SolidQueue(ジョブキュー)・SolidCache(キャッシュ)・SolidCable(ActionCableメッセージ) が標準搭載
  • これらは 既存のRDBMS(PostgreSQL/SQLite/MySQL)上で動作 し、 Redisの役割を完全に代替
  • ほとんどのRailsアプリで Redisを削除可能、運用コスト・複雑さの低減

Redis運用の隠れたコスト

  • Redisサーバのデプロイ・バージョン管理・パッチ適用・監視 の必要性
  • 永続化戦略(RDB/AOF/両方)・メモリ制限・エビクションポリシー の設定
  • ネットワーク接続・ファイアウォール・クライアント認証・HA構成 の維持
  • Sidekiqプロセスのオーケストレーション異なるデータストア(RDBMS/Redis)間のデバッグ の煩雑さ
  • バックアップ戦略の二重管理 も必要

SolidQueueの仕組み

  • PostgreSQL 9.5以降のFOR UPDATE SKIP LOCKED を活用して、 ロック競合せずにジョブを分配
  • ジョブの状態管理用テーブル:
    • solid_queue_jobs (全ジョブのメタデータ記録)
    • solid_queue_scheduled_executions (スケジュール待ちジョブ)
    • solid_queue_ready_executions (即時実行待ちジョブ)
  • ワーカーはreadyテーブルをポーリングし、SKIP LOCKEDで同時にジョブ取得
  • MVCC+autovacuum で大量のinsert/deleteにも耐性

定期実行ジョブ(Recurring Jobs)

  • Sidekiqではsidekiq-cron等が必要 だが、 SolidQueueはcron風定期実行を標準搭載
  • config/recurring.yml でスケジュール記述
  • GoodJob由来の決定論的スケジューリング でクラッシュ耐性

ジョブ同時実行数制限(Concurrency Limit)

  • Sidekiq Enterpriseの有償機能 だったが、 SolidQueueは標準で対応
  • limits_concurrency で単位ごとの同時実行数・期間を制御
  • solid_queue_semaphores/blocked_executions テーブルで待機ジョブ管理
  • ジョブ終了時に自動で次のジョブをアンブロック

Mission Controlによる監視・管理

  • Mission Control Jobs はSolidQueue専用の無料・OSSダッシュボード
  • リアルタイム状態・失敗ジョブ・リトライ・スケジュール可視化・メトリクス を提供
  • SQLで直接ジョブデータをクエリ可能、外部ツール不要

SidekiqからSolidQueueへの移行手順

  • queue_adapterを:solid_queueに変更
  • SolidQueue gem導入・マイグレーション実行
  • Sidekiq-cron等のスケジュールをrecurring.ymlへ変換
  • Procfileのjobsプロセスをsolid_queue:startに変更
  • Redis/Sidekiq関連gemを削除し、bundle clean

SolidQueueが適さないケース

  • 常時数千ジョブ/秒以上の高負荷
  • 1ms未満の超低レイテンシが必須
  • 複雑なpub/subやレート制限・カウンター用途
  • 例:リアルタイムビッディング、HFT、Shopify級の超大規模

実用的なSolidQueueセットアップ例

  • 新規Rails 8アプリ作成時、SolidQueue/SolidCache/SolidCableは自動設定
  • queue用DB接続をdatabase.ymlで分離推奨
  • Mission Controlの認証設定・マウント
  • Procfileでjobsプロセス追加
  • テストジョブで動作確認
  • 単一DB運用も可能だが、分離接続が推奨

よくある注意点・運用Tips

  • Mission Controlの本番運用時は認証強化必須
  • ポーリング間隔調整でレイテンシ最適化可能
  • ActionCable/Turbo Streams利用時はSolidCable用DB接続も設定
  • サーバ起動時にすべてのプロセスを同時起動

スケーラビリティとパフォーマンス

  • ほとんどのRailsアプリはSolidQueueで十分スケール
  • 例:37signalsはPostgreSQLのみで日2,000万ジョブ処理
  • Redis+Sidekiqに比べ、運用シナリオ・障害パターンが少なくシンプル
  • 99%以上のRailsアプリでSolidQueueが最適解

まとめ

  • Redis/Sidekiqの組み合わせは依然優秀 だが、 ほとんどのRails 8アプリはSolidQueueで十分
  • インフラのシンプル化と運用負荷の軽減 が最大のメリット
  • 新しいRails 8の流儀としてSolidQueue導入を推奨
  • フィードバックや意見も歓迎

Hackerたちの意見

環境をシンプルにできるたびに、いいニュースだと思う。Railsの理想は、Redisに簡単に戻せる方法があればいいなって感じ。シンプルに始めて、SolidQueueを使っていて根本的な問題(たぶんスケーラビリティの問題だと思う)にぶつかったら、簡単にアップグレードできる道筋があるといいよね。だけど、99%のRailsアプリはそんなにトラフィックがないから、2つのシステムを維持するのは余計な複雑さになっちゃうかも。

ここでの問題は、バックグラウンドジョブやタスクプロセッサを生産システムの一部として扱っちゃうことだと思う(例えば、ウェブアプリのリクエストに応答するサーバーみたいに)。Railsはこの区別があまり明確じゃない。タスクプロセッサをpgデータベースでバックアップするのは全然問題ないけど(例えば、river[0])、間接的に指摘したように、生産データベースと同じにすべきじゃない。だからRedisが好まれたんだよね。タスクプロセッサの状態を保存するための軽量データベースだったし。この設定にはまだ大きな利点があると思う。今のところ、SolidQueueはこの分離をしてないみたい。 [0]: https://riverqueue.com/

ここでの主な問題点は、開発者がトランザクションに依存しすぎて、仕事が他のすべての処理と一緒に作られることだと思う。保証がなくなると、最終的な移行が難しくなるかもしれない。たとえそれがプライマリDBとは別のPostgresインスタンスへの移行でもね。

Railsの理想的な状況は、Redisに戻る簡単な方法があることだね。 それはほぼその通りだよ。Railsはジョブ用に抽象化されたAPI(Active Job)を提供してるからね。もちろん、特定のキュー実装に依存してるアプリもあるけど、一般的には設定を更新するだけで切り替えられるし(もちろん古いキューを処理するのも忘れずに)。

Postgresは世界を飲み込む。

確かに、Postgresは世界を飲み込む。pg_kernel拡張が出るのを待ってるから、やっとLinuxをアンインストールできるかも :)

RDMSが世界を飲み込む。結局、機能セットの問題だね。

今はPGQMとPG_CRONを使ってるけど、もう戻れないね。MySQL + Redis + AWSのelasti-cron(とかなんとか)は、Postgresに比べたらゴミみたいなもんだった。

でもMySQLの方が扱いやすいかな。Postgres派として言うけど、MySQLはメンテナンスが少なくてパフォーマンスもいいよ。

せめて数年後には、人々が「すべてにPostgres」っていう流行が「すべてにMongoDB」とか「すべてにRedis」っていうのと同じくらい悪いアイデアだって気づくんじゃないかな。

スケールしないと思ってる人へ。Elixirの似たような実装はObanだよ。彼らのベンチマークでは、単一ノードで毎分100万ジョブを処理できるって。もっと最適化すればさらに増やせると思う。99.99999%のアプリは毎分100万件のバックグラウンドジョブには達してないだろうね。 https://oban.pro/articles/one-million-jobs-a-minute-with-oba...

このベンチマークは、アプリケーションがタスクキューを使う方法からかなりかけ離れてると思う。見出しは「1分間に100万ジョブ」って書いてあるけど、これは本当だよ。ただし… - これは5000ジョブのバッチをキューに入れることで達成されてるから、キュー側では実際には100万TPSじゃなくて200TPSなんだ。バックグラウンドジョブの作成でそんなにバッチ処理を見たことがない。 - ディスパッチも数百TPS(5ms…2ms)にバッチ処理されてる。 - 確認応答もバッチ処理されてる。だから、17kジョブ/秒に到達するために期待される~50-100k TPSではなく、SQL側ではおそらく数百トランザクション/秒しか処理してないと思う。それに、すべてをバッチ処理しないと(ジョブの提出、確認応答;ディスパッチは妥当)、スループットはそのレベルに落ちる可能性が高くて、期待にもっと合致すると思う。このベンチマークは、むしろ「for i in range(5000)」のループを1分以内に200回呼び出すことに近いと思うけど、ほとんどのDB(SQLiteでも)なら処理できると思うよ。

Hacker Newsで議論の続きを見る