Rails 8のSolid QueueとSolid Cache:2026年技術面接完全ガイド
Rails 8で標準搭載されたSolid QueueとSolid Cacheを解説。ジョブバッチ、Fiber実行モード、Active Job Continuations、面接頻出の知識を2026年版にアップデート。

Solid QueueとSolid Cacheは、Railsの歴史において最も大きなインフラストラクチャの転換を象徴するコンポーネントです。Rails 8ではいずれもデフォルトとして搭載され、バックグラウンドジョブとキャッシュにおけるRedis依存を排除し、データベースバックエンドによる代替手段を提供します。運用上の複雑さが一つの層ごと取り除かれることになります。
Rails 8はデータベースバックエンドの3つのコンポーネントをデフォルトとしています。Solid Queue(バックグラウンドジョブ)、Solid Cache(キャッシュストア)、そしてSolid Cable(WebSocket)です。これらを組み合わせることで、ほとんどのRailsアプリケーションからRedis依存を排除できます。Rails 8の技術面接では頻出のトピックです。
Solid QueueがRedisベースのジョブバックエンドを置き換える仕組み
Solid Queueは、PostgreSQL、MySQL、SQLiteにジョブを直接保存するデータベースバックエンドのActive Jobバックエンドです。核心となるメカニズムは FOR UPDATE SKIP LOCKED です。これはPostgreSQL 9.5以降およびMySQL 8以降で利用可能なSQL機能で、通常のデータベーステーブルをブロッキングなしの並行ジョブキューに変換します。
アーキテクチャは3つのコンポーネントで構成されています。
- Worker は
solid_queue_ready_executionsテーブルをポーリングし、SKIP LOCKEDを使用してジョブを取得します - Dispatcher はスケジュールされたジョブを
solid_queue_scheduled_executionsから実行時刻到達時にreadyテーブルへ移動します - Scheduler は設定ファイルで定義された定期タスクを管理します
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
polling_interval: 0.1
processes: 2この設定では、2つのワーカープロセスがそれぞれ5スレッドで動作し、100ミリ秒ごとにポーリングします。Dispatcherは1秒ごとに500件のバッチでスケジュール済みジョブを確認します。
Rails 8におけるトランザクショナルジョブエンキュー
Solid QueueがRedisベースのバックエンドに対して持つ最も強力な優位性の一つが、トランザクショナルエンキューです。データベーストランザクション内でエンキューされたジョブは、トランザクションがコミットされた後にのみ可視化されます。Redisベースのバックエンドではこの保証を提供できません。ジョブがトリガー元のトランザクション完了前に実行され、まだ存在しないレコードを参照してしまう可能性があります。
# 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
endenqueue_after_transaction_commit を有効にすると、ジョブはラップしているトランザクションが成功するまで遅延されます。トランザクションがロールバックされた場合、ジョブはエンキューされません。これにより、Redisバックエンドのキューで問題となるレースコンディションのクラス全体が排除されます。
同時実行制御とプライオリティキュー
Solid Queueは、Sidekiqでは有料のEnterprise版でのみ提供される組み込みの同時実行制御を備えています。concurrency_limit オプションにより、特定の種類のジョブが同時に実行できる数を制限できます。
# 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
endこの設定により、アカウントごとに最大3つのAPI同期ジョブしか同時実行されません。外部の調整メカニズムなしにレート制限違反を防止できます。ブロックされたジョブは solid_queue_blocked_executions に保存され、スロットが空くと自動的にリリースされます。
プライオリティは2つのレベルで機能します。ジョブごとの数値プライオリティ(数値が小さいほど優先度が高い)と、ワーカー設定でのキュー順序です。両方を組み合わせることで、ジョブ実行順序をきめ細かく制御できます。
Rails 8の面接でよく出る質問に、Solid QueueとSidekiqのトレードオフがあります。主な差別化ポイントは、Solid Queueがトランザクション保証と組み込みの同時実行制御を無料で提供することです。Sidekiqは、Redisがインメモリであるため、高ボリュームのワークロード(毎分10,000ジョブ以上)において生のスループットで優位に立ちます。95%のアプリケーションにとって、Solid Queueは十分なパフォーマンスを提供します。詳細なベンチマークはRailsバックグラウンドジョブ比較を参照してください。
グループ操作のためのジョブバッチ
Solid Queue 1.7.0でジョブバッチが導入され、ジョブをセットとしてグループ化して追跡できるようになりました。この機能により、バッチ内のすべてのジョブが完了したときにコールバックを実行できます。従来は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
endバッチはブロック内でエンキューされたすべてのジョブを追跡します。すべてのジョブが終了すると、成功・失敗に関わらず on_finish が実行されます。すべてのジョブが成功した場合は on_success が実行され、いずれかが失敗した場合は on_failure が実行されます。これにより、インポート処理のような最終ステップがすべての部分の完了を待つ必要があるワークフローが可能になります。
バッチの外部で作成されたジョブでも、内部でエンキューされればそのバッチに参加します。ジョブが0件のバッチは即座に終了し、コールバックがすぐに実行されます。
I/O集約型ワークロードのためのFiber実行モード
Solid Queue 1.6.0で、Asyncgemを使用したFiberベースのワーカー実行が追加されました。このモードはスレッドではなくFiberでジョブを実行し、LLM APIコールのようなレスポンス待ちに大半の時間を費やすI/O集約型ワークロードに適しています。
# config/solid_queue.yml
production:
workers:
- queues: [llm_calls, external_apis]
fibers: 100
polling_interval: 0.5100のFiberで、単一プロセス内で最小限のメモリオーバーヘッドで100の並行I/Oバウンドジョブを実行できます。100スレッドと比較すると、メモリ消費量が大幅に少なく、GVL(Global VM Lock)での競合も軽減されます。
FiberモードにはRailsのFiber分離設定が必要です。
# config/application.rb
config.active_support.isolation_level = :fiberCPU集約型のジョブは引き続きスレッドを使用すべきです。I/Oにyieldしない処理ではFiberのメリットはありません。
Rails 8.1のActive Job Continuations
Rails 8.1でActive Job Continuationsが導入され、長時間実行ジョブをチェックポイントで一時停止し、再開できるようになりました。デプロイやコンテナ再起動で中断されたジョブが最初からやり直す問題を解決します。
# 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
endstep メソッドは個別のステージを定義します。ジョブが中断された場合、最後に完了したステップから再開されます。ステップ内では step.cursor が進捗を追跡し、step.advance!(from: record.id) でカーソル位置を保存します。再開時には find_each(start: step.cursor) が処理を中断箇所から継続します。
Continuationsはキューアダプタが stopping? を実装している必要があります。Solid Queueはv1.2.0からサポートしています。Delayed JobとResqueは追加作業なしではグレースフルな中断をサポートしていません。
カーソルはシリアライズ可能な任意の値を取れます。ネストしたループでは配列を使用します。
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
endCronを使わない定期ジョブ
Solid Queueは、cronベースのスケジューリングを組み込みのスケジューラーで置き換えます。定期タスクはYAML設定ファイルで定義され、スケジューラープロセスによって管理されます。
# 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 9amスケジューラープロセスがこのファイルを読み込み、定義された間隔で適切なジョブをエンキューします。cronとは異なり、同じプロセススーパーバイザー内で動作し、同じデータベース接続を共有します。タイムゾーンサポートはSolid Queue 1.5.0で追加されました。
Puma統合によるデプロイ
Rails 8は Kamal と組み合わせることで、Solid Queueのゼロコンフィグデプロイを実現します。SOLID_QUEUE_IN_PUMA=1 を設定すると、PumaがWebサーバーと並行してSolid Queueプロセスをフォークして監視します。
# config/puma.rb (Rails 8 default)
plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"]このシングルプロセスデプロイモデルにより、コンテナオーケストレーションが簡素化されます。1つのDockerイメージでWebサーバーとジョブプロセッサの両方を実行でき、中小規模のアプリケーションの運用オーバーヘッドを削減できます。
Ruby on Railsの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
Solid Cache:スケーラブルなデータベースバックエンドキャッシュ
Solid Cacheは、データベースバックエンドの ActiveSupport::Cache::Store であり、最新のSSD性能を活用してRedisとMemcachedをデフォルトのキャッシュストアとして置き換えます。その前提は、SSDの読み取り性能がRAMと比較してわずかに劣るだけであり、はるかに大きなストレージ容量をはるかに低いコストで提供できるということです。Solid Cacheは10TBと60日間の保持でBasecampの本番環境で稼働しており、P95レンダリング時間を半減させています。
Solid CacheはLRU(Least Recently Used)ではなくFIFO(First In, First Out)の有効期限戦略を採用しています。FIFOは理論的にはLRUほど効率的ではありませんが、はるかに大きなストレージ容量がこれを補います。エントリはより長期間キャッシュに残り、全体的なキャッシュミスが減少します。
# 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 cycleキャッシュアーキテクチャと有効期限メカニズム
Solid Cacheは内部カウンターを使用して書き込みを追跡します。カウンターが設定された expiry_batch_size の50%に達すると、期限切れエントリをクリーンアップするバックグラウンドタスクがトリガーされます。この償却アプローチにより、メモリ制約のあるRedisインスタンスでLRUエビクション時に発生する可能性のあるストップ・ザ・ワールド一時停止を回避できます。
solid_cache_entries テーブルにすべてのキャッシュデータが保存されます。
# 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
endこのテーブルの読み書きは、デフォルトではアプリケーションの他の部分と同じコネクションプールを使用します。高トラフィックのアプリケーションでは、キャッシュデータ専用のデータベースを構成することで、キャッシュの入れ替えがプライマリデータベースのパフォーマンスに影響を与えることを防げます。
キャッシュ用の独立データベース構成
Solid Cacheを専用データベースに分離することは容易であり、大量のキャッシュトラフィックが発生する本番ワークロードでは推奨されます。
# config/database.yml
production:
primary:
<<: *default
database: myapp_production
cache:
<<: *default
database: myapp_cache_production
migrations_paths: db/cache_migrateこの分離により、数百万のキャッシュ書き込み操作がプライマリデータベースのWAL(Write-Ahead Log)を肥大化させたり、アプリケーションクエリとコネクションプールのスロットを競合させたりすることを防止できます。
専用データベースを使用しない場合、Solid Cacheの読み書きはラップしている ActiveRecord トランザクションに参加します。これは、長時間実行されるトランザクションがキャッシュエントリをコミットされていない状態で保持することを意味します。本番アプリケーションでは、必ず専用のキャッシュデータベースを構成してください。
シャーディングと暗号化
Solid Cacheは、負荷分散のためにキャッシュデータを複数のデータベースにシャーディングすることをサポートしています。また、暗号化属性もサポートしており、キャッシュデータは保存時に暗号化されたままとなります。これは機密情報を扱うアプリケーションのコンプライアンス要件です。
# config/solid_cache.yml
production:
databases:
- cache_shard_1
- cache_shard_2
- cache_shard_3
store_options:
max_age: 1209600 # 2 weeksエントリはキャッシュキーのコンシステントハッシュを使用してシャード間に分散されます。シャードの追加や削除により、エントリが再分散される間は一時的にキャッシュミスが増加しますが、データ損失は発生しません。
Mission Control Jobsによる監視
Mission Control Jobs は、Solid Queueジョブの検査と管理のためのWebダッシュボードを提供します。マウントされたRailsエンジンを通じて、ワーカー、キュー、ジョブの状態(実行中、完了、ブロック、失敗)を表示します。
# 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は、失敗したジョブの一括操作のためのコンソールAPIも公開しています。
# Rails console
ActiveJob.jobs.failed.where(job_class: "ApiSyncJob").retry_all
ActiveJob.jobs.failed.where(job_class: "BrokenJob").discard_allこのプログラムによるアクセスは、ダッシュボードを手動でクリックすることなく大規模なジョブの失敗を処理するために不可欠です。
ソース
- Rails 8.0 Release Notes - Solid QueueとSolid Cacheのデフォルト設定に関する公式ドキュメント
- Solid Queue GitHub Releases - バッチ(v1.7.0)、Fiberモード(v1.6.0)、Continuationsサポート(v1.2.0)のChangelog
- Active Job Continuations PR - Rails 8.1の実装詳細
- Introducing Solid Queue (37signals) - 設計思想とHEYでの本番運用
技術面接の頻出質問
Rails 8の面接では、Solidスタックに焦点が当てられることが増えています。以下は最もよく出る質問と、期待される回答の深さです。
Q: Solid QueueはRedisなしでどのように並行ジョブ処理を実現していますか?
Solid Queueは FOR UPDATE SKIP LOCKED というSQL句を使用します。これにより、複数のワーカーが互いをブロックすることなく同じテーブルをポーリングできます。各ワーカーは行のバッチをロックし、処理後に実行レコードを削除します。他のワーカーはロック済みの行をスキップして別のジョブを取得します。
Q: トランザクショナルエンキューはどのような問題を解決しますか?
ジョブをトリガーしたデータベーストランザクションがコミットされる前にジョブが実行されることを防ぎます。これがないと、ロールバックされたレコードをジョブが参照し、ActiveRecord::RecordNotFound エラーを引き起こす可能性があります。
Q: Solid CacheがLRUではなくFIFOを使用する理由は何ですか? FIFOはデータベースでの実装がシンプルで、読み取りごとにアクセスタイムスタンプを更新する書き込み増幅を回避できます。SSDの大容量ストレージにより、エントリはより長期間保持されるため、最適でないエビクション戦略にもかかわらず高いヒット率が維持されます。
Q: Solid Queueのジョブバッチはどのように機能しますか?
SolidQueue::Batch.enqueue ブロック内でエンキューされたジョブはまとめて追跡されます。すべてのジョブが完了すると on_finish が実行され、すべて成功すれば on_success、いずれかが失敗すれば on_failure が実行されます。これにより、バッチインポートのような最終ステップがすべての部分の完了に依存するワークフローが可能になります。
Q: Active Job Continuationsとは何ですか。いつ使用すべきですか? Continuationsは長時間実行ジョブが進捗をチェックポイントし、中断後に再開できるようにします。インポートやバッチ更新のような大規模データセットを処理するジョブに使用します。デプロイごとに最初からやり直すと膨大な時間とリソースの無駄になる場合に有効です。
Q: アプリケーションがSolidスタックではなくRedisを使用すべき場合はどのような場合ですか? Redisは、毎分10,000件以上のジョブを処理するアプリケーション、サブミリ秒のキャッシュ読み取りが必要なワークロード、または他の目的(Pub/Sub、レート制限、セッションストレージ)でRedisを既に使用しているアプリケーションにおいて引き続き優位です。Solidスタックはピークスループットではなく、シンプルさを目標としています。
これらの質問の練習は SharpSkillのActiveJob & バックグラウンドジョブモジュール と キャッシュ戦略モジュール で行えます。
Ruby on Railsの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
Rails 8のSolid QueueとSolid Cacheで押さえておくべきポイント
- Solid Queueは、
FOR UPDATE SKIP LOCKEDを使用した並行処理により、Redisバックエンドのジョブキューをデータベースバックエンドのソリューションに置き換えます - トランザクショナルエンキューにより、データベース書き込みとジョブ実行間のレースコンディションが排除されます。これはRedisでは提供できない保証です
- ジョブバッチ(v1.7.0)により、完了コールバック付きのグループ操作が可能になりました。以前はSidekiq Pro限定の機能でした
- Fiber実行モード(v1.6.0)により、LLM APIコールのようなI/O集約型ワークロードのスループットが向上します
- Active Job Continuations(Rails 8.1)により、長時間実行ジョブを中断後にチェックポイントから再開できます
- 組み込みの同時実行制御、定期ジョブ、Puma統合がSolid Queueに追加コストなしで同梱されています
- Solid CacheはSSDバックエンドのFIFOキャッシュを提供し、オプションのシャーディングと暗号化により、MemcachedとRedisをインフラストラクチャスタックから排除します
- Solid Cacheの専用データベース構成により、キャッシュの入れ替えがプライマリデータベースのパフォーマンスに影響を与えることを防止します
- Mission Control JobsはWebダッシュボードとコンソールAPIを通じて、本番環境の監視と一括ジョブ管理を提供します
- 2026年のほとんどのRails 8アプリケーションにとって、Solidスタックが推奨デフォルトです。Redisは毎分10,000ジョブを超える高スループットのエッジケースでのみ選択肢となります
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
Ruby on Rails のバグを見つけられますか
実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

執筆
Anthony Fillion-MailletSharpSkill 創業者
10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。
2026年10月10日 更新
タグ
共有
関連記事

Rails バックグラウンドジョブ 2026年版:Sidekiq vs Good Job の徹底比較と面接対策
2026年のRailsにおけるバックグラウンドジョブ処理を徹底解説。Sidekiq、Good Job、Solid Queueの特徴を比較し、技術面接でよく出題される質問と回答例を紹介します。

Ruby on Rails 8 新機能完全ガイド:Solid Trifecta・認証・移行手順を徹底解説【2026年版】
Rails 8の新機能を徹底解説。Solid Trifecta(Queue/Cache/Cable)によるRedis不要化、組み込み認証、Propshaft、Kamal 2デプロイ、Rails 7からの移行手順まで網羅。

2026年のフリーランスRuby on Rails開発者の仕事:案件の探し方、単価相場、準備方法
2026年、フリーランスRuby on Rails開発者として活躍するための完全ガイド。案件の見つけ方、日本と海外の単価相場、契約形態、技術面接対策まで詳しく解説します。