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

Railsのバックグラウンドジョブは、Rails 8.xとSolid Queueのデフォルト採用により大きく進化しました。Sidekiq、Good Job、Solid Queueの選択は、スループット要件、インフラ構成、必要な機能によって決まります。
新規のRails 8プロジェクトでは、まずSolid Queueから始めることを推奨します。1日10万件を超える高スループットワークロードやRedisレベルのレイテンシが必要な場合はSidekiqに切り替えてください。PostgreSQLベースでバッチ処理やユニークジョブ制約が必要な場合はGood Jobが適しています。
Active Jobによるバックグラウンド処理の統一化
Active Jobは、Railsでバックグラウンド処理を宣言、キューイング、実行するための標準インターフェースを提供します。このフレームワークはキューバックエンド間の差異を抽象化し、Sidekiq、Good Job、Solid Queueなど様々なアダプタ間でコードの移植性を維持できます。
# app/jobs/payment_processor_job.rb
class PaymentProcessorJob < ApplicationJob
queue_as :critical
retry_on Stripe::RateLimitError, wait: :polynomially_longer, attempts: 5
discard_on Stripe::InvalidRequestError
def perform(order_id)
order = Order.find(order_id)
PaymentService.process(order)
OrderMailer.confirmation(order).deliver_later
end
endretry_onとdiscard_onコールバックは、バックエンド固有のコードなしで一時的な障害と永続的なエラーを処理します。queue_asディレクティブは優先度を割り当て、各バックエンドは独自のキュー処理戦略に従って解釈します。
Sidekiq 8.x:Redisベースの高スループット
Sidekiqは、Railsバックグラウンドジョブのパフォーマンス基準として位置づけられています。8.xリリースシリーズでは、Ruby 3.2以上、Rails 7.0以上、Redis 7.2以上が必要です(Redisがライセンス変更したため、ValkeyとDragonflyがドロップイン代替として動作します)。
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: ENV.fetch('REDIS_URL') }
config.concurrency = 10
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV.fetch('REDIS_URL') }
endSidekiq 8では3つの主要な変更が導入されました。Web UIが完全に書き直され、CSSが160KBから16KBに削減、平均ページレンダリング時間が55msから3msに短縮されました。Vernierを使用したジョブプロファイリングが新しいProfilesタブで利用可能になり、ジョブメトリクスが最大72時間保持されるようになりました。
Sidekiqが適しているケース
Sidekiqは、持続的なスループット、サブミリ秒のジョブ取得レイテンシ、またはレート制限やユニークジョブなどのエンタープライズ機能がRedis運用を正当化するワークロードに適しています。7.0で導入され現在は標準となったCapsulesにより、1つのSidekiqプロセスで独自の並行性とキューを持つ複数の分離されたスレッドプールを実行できます。
# config/sidekiq.yml
:concurrency: 10
:queues:
- [critical, 3]
- [default, 2]
- [low, 1]
# 分離処理用のCapsules
:capsules:
imports:
:concurrency: 2
:queues:
- imports埋め込みAPIにより、Solid QueueのPumaプラグインと同様に、小規模アプリケーションではSidekiqをPumaプロセス内で実行することも可能です。
Ruby on Railsの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
Good Job 4.x:PostgreSQLネイティブのバッチ処理とユニーク性
Good Jobは、PostgreSQLのLISTEN/NOTIFYをジョブ取得に、アドバイザリロックを一度だけ実行の保証に使用します。バージョン4.19.x(2026年9月現在)はRails 6.1以上とRuby 3.0以上をサポートしています。
# config/application.rb
config.active_job.queue_adapter = :good_job
# config/initializers/good_job.rb
Rails.application.configure do
config.good_job.execution_mode = :async
config.good_job.max_threads = 5
config.good_job.poll_interval = 5
config.good_job.shutdown_timeout = 25
endGood Jobは、Sidekiqが有料ライセンスで提供しているバッチ処理とユニークジョブ機能をオープンソース版で提供しています。perform_later呼び出しは呼び出し元コードと同じデータベーストランザクション内でgood_jobsテーブルに行を挿入するため、トランザクションがロールバックするとジョブは作成されません。
ライセンス不要のバッチ処理
# app/jobs/batch_import_job.rb
class BatchImportJob < ApplicationJob
def perform(batch, params)
batch.on(:finish, ImportCompletionJob, params)
params[:file_ids].each do |file_id|
batch.add do
ProcessFileJob.perform_later(file_id)
end
end
end
end
# バッチをエンキュー
GoodJob::Batch.enqueue do |batch|
BatchImportJob.perform_later(batch, file_ids: [1, 2, 3])
end冪等性のためのユニークジョブ
# app/jobs/sync_inventory_job.rb
class SyncInventoryJob < ApplicationJob
include GoodJob::ActiveJobExtensions::UniqueJob
good_job_control_concurrency_with(
perform_limit: 1,
key: -> { "sync_inventory_#{arguments.first}" },
duration: 1.hour
)
def perform(warehouse_id)
InventorySync.run(warehouse_id)
end
endperform_limit: 1制約により、各倉庫で同時に実行される同期は1つだけとなり、同じジョブが複数回キューイングされた場合の重複作業を防ぎます。
Solid Queue:Rails 8のデフォルト
Solid Queueは、PostgreSQLとMySQLの機能であるFOR UPDATE SKIP LOCKEDを使用して、通常のテーブルをジョブキューに変換し、アプリケーションデータベースにジョブを保存します。新しいRails 8アプリケーションは、Solid Queueが設定済みの状態で出荷されます。
# config/solid_queue.yml
production:
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 5
polling_interval: 0.1Solid QueueはSOLID_QUEUE_IN_PUMA=trueでPuma Webサーバープロセス内で実行でき、専用のワーカープロセスを必要としないアプリケーションのデプロイを簡素化します。ジョブはデータベーステーブルに永続化され、外部依存関係なしでプロセスの再起動やデプロイを生き延びます。
機能比較表
| 機能 | Sidekiq 8.x | Good Job 4.x | Solid Queue 1.x |
|---|---|---|---|
| バックエンド | Redis 7.2以上 | PostgreSQL | PostgreSQL/MySQL/SQLite |
| バッチ処理 | Pro/Enterprise | 含む | 計画中 |
| ユニークジョブ | Enterprise | 含む | 手動ロック |
| Cronスケジューリング | Enterprise | 含む | solid_queue_cron経由 |
| Web UI | 含む | 含む | 最小限(Mission Control) |
| スループット上限 | 10万件以上/分 | 1万件/分 | 1万件/分 |
| Pumaへの埋め込み | 可能(8.x) | 不可 | 可能 |
| ライセンス | LGPL + 商用 | MIT | MIT |
Railsバックグラウンドジョブに関する面接質問
技術面接では、ジョブの信頼性、リトライ戦略、アーキテクチャ決定に関する理解がよく問われます。以下は、経験豊富な候補者を見分けるための質問です。
Q1:retry_onとバックエンド固有のリトライロジックの違いは何ですか?
retry_onはすべてのバックエンドで動作するActive Jobコールバックです。特定の例外をキャッチし、待機戦略(:polynomially_longerは指数バックオフ)を適用し、ジョブを再キューイングします。Sidekiqのsidekiq_retry_inなどのバックエンド固有のリトライロジックは、そのバックエンドでのみ動作し、Active Jobの動作をオーバーライドする可能性があります。
# Active Jobリトライ(移植可能)
class ApiSyncJob < ApplicationJob
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 8
def perform(record_id)
ExternalApi.sync(record_id)
end
endQ2:ジョブをキューイングしたデータベーストランザクションがロールバックした場合、ジョブはどうなりますか?
データベースベースのキュー(Good Job、Solid Queue)では、ジョブ行はトランザクションの一部であるため、他のすべてと一緒にロールバックされます。Redisベースのキュー(Sidekiq)では、トランザクションが完了する前にジョブはすでにRedisにあり、孤立したジョブが作成されます。回避策はafter_commitコールバックです。
# Sidekiqの正しいパターン
class Order < ApplicationRecord
after_commit :enqueue_confirmation, on: :create
private
def enqueue_confirmation
OrderConfirmationJob.perform_later(id)
end
endQ3:Good JobがSidekiqを上回るのはどのような場合ですか?
Good Jobは、Redisの運用コストがそのスループット利点を上回る場合にSidekiqを上回ります。1日5万件未満のジョブを処理するアプリケーションでは、PostgreSQLベースのキューにより、別のRedisクラスタのインフラ、監視、フェイルオーバーの複雑さを回避できます。Good Jobはライセンス料なしでバッチ処理とユニークジョブも提供しており、予算内でこれらの機能が必要なチームにとって重要です。
Q4:ジョブの冪等性とリトライにとって重要な理由を説明してください
冪等性とは、同じジョブを複数回実行しても1回実行したのと同じ結果になることを意味します。ネットワーク障害、プロセスクラッシュ、タイムアウト処理により重複実行が発生する可能性があるため、ジョブは冪等でなければなりません。手法には、データベースのユニーク制約、処理前の既存結果の確認、決済APIの外部冪等性キーの使用などがあります。
# 冪等な決済処理
def perform(order_id, idempotency_key)
return if Payment.exists?(idempotency_key: idempotency_key)
Payment.create!(
order_id: order_id,
idempotency_key: idempotency_key,
amount: Order.find(order_id).total
)
endQ5:分散ワーカー間でジョブを正確に1回だけ実行する方法は?
分散ロックにより同時実行を防ぎます。Good JobはPostgreSQLアドバイザリロックを使用します。Sidekiq Enterpriseはユニークジョブを提供します。手動実装の場合は、RedisのSETNXまたはPostgreSQLのpg_try_advisory_lockを使用します。
class ExclusiveJob < ApplicationJob
def perform(resource_id)
lock_key = "exclusive_job:#{resource_id}"
ActiveRecord::Base.connection.execute(
"SELECT pg_try_advisory_lock(hashtext('#{lock_key}'))"
).first['pg_try_advisory_lock'] or return
begin
process_resource(resource_id)
ensure
ActiveRecord::Base.connection.execute(
"SELECT pg_advisory_unlock(hashtext('#{lock_key}'))"
)
end
end
end今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
Railsバックグラウンドジョブに適したバックエンドの選択
- スタックにまだRedisがない新しいRails 8プロジェクトでは、Solid Queueから始める
- ジョブ量が1日5万件を超える場合や100ms未満の取得レイテンシが重要な場合は、Sidekiqに切り替える
- ライセンスコストなしでバッチ処理、ユニークジョブ、またはCronスケジューリングが必要なPostgreSQL専用デプロイにはGood Jobを選択する
- Sidekiqでジョブをキューイングする際は
after_commitコールバックを使用し、トランザクションロールバック時の孤立ジョブを回避する - リトライと分散処理により重複実行が発生する可能性があるため、すべてのジョブを冪等にする
- 面接では、トランザクション内ジョブキューイング、リトライ戦略、分散ロックパターンの理解を示すことが重要
Ruby on Rails のバグを見つけられますか
実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

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

Rails 8のSolid QueueとSolid Cache:2026年技術面接完全ガイド
Rails 8で標準搭載されたSolid QueueとSolid CacheがRedisを置き換える仕組みを解説。アーキテクチャ、設定、同時実行制御、2026年の面接頻出質問まで網羅。

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

Rails GraphQL API 2026年版: graphql-ruby、サブスクリプション、面接対策質問集
graphql-rubyを使用したRails GraphQL APIの構築方法を解説。DataLoaderによるN+1対策、ActionCableサブスクリプション、RSpecテスト、実践的な面接質問を網羅的にカバーします。