投稿日:2026/7/21
更新日:2026/7/22

重い処理(メール送信・CSV処理・外部API呼び出しなど)をバックグラウンドで実行する仕組み。
キューイングには Redis を使い、Sidekiq ワーカーが順次処理する。
Rails で Sidekiq を使う書き方は大きく2つある。
| 書き方 | ジョブ定義 | 呼び出し |
|---|---|---|
| ActiveJob 経由 | class WelcomeEmailJob < ApplicationJob |
perform_later / perform_now |
| Sidekiq ネイティブ | include Sidekiq::Job |
perform_async / perform_in / perform_at |
ApplicationJob に対して perform_async を使う、というような混ぜ方は避ける。
Rails 標準の ApplicationJob を使うなら perform_later、Sidekiq の API を直接使うなら include Sidekiq::Job に揃える。
ActiveJob 経由で Sidekiq を使う場合は、ActiveJob の adapter を Sidekiq にしておく。
# config/application.rb など
config.active_job.queue_adapter = :sidekiq
class WelcomeEmailJob < ApplicationJob
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
end
end
perform メソッドに実際の処理を書くfind する方が扱いやすい# 非同期実行(キューに積むだけ。即返る)
WelcomeEmailJob.perform_later(user.id)
# 指定時間後に実行
WelcomeEmailJob.set(wait: 10.minutes).perform_later(user.id)
# 指定日時に実行
WelcomeEmailJob.set(wait_until: Time.zone.tomorrow).perform_later(user.id)
# キューに積まず、その場で同期実行
WelcomeEmailJob.perform_now(user.id)
perform_now 以外は Sidekiq にジョブを登録する処理。
ただし、保存される場所と通常キューへ入るタイミングが違う。
perform_later は即実行対象として、すぐ通常のキューに積まれるset(wait: ...) は指定時間後に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移されるset(wait_until: ...) は指定日時に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移されるperform_now はキューに積まず、現在のプロセスで perform をそのまま実行するperform_async などの Sidekiq ネイティブ API を使う場合は、ApplicationJob ではなく Sidekiq::Job を include する。
class WelcomeEmailJob
include Sidekiq::Job
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
end
end
# 非同期実行(すぐ通常キューに積む)
WelcomeEmailJob.perform_async(user.id)
# 指定時間後に実行
WelcomeEmailJob.perform_in(10.minutes, user.id)
# 指定日時に実行
WelcomeEmailJob.perform_at(Time.zone.tomorrow, user.id)
# 複数ジョブをまとめて投入
WelcomeEmailJob.perform_bulk([[1], [2], [3]])
# キューに積まず、その場で実行
WelcomeEmailJob.perform_inline(user.id)
WelcomeEmailJob.perform_sync(user.id) # perform_inline の alias
perform_async / perform_in / perform_at は、いずれも Sidekiq にジョブを登録する処理。
ただし、保存される場所と通常キューへ入るタイミングが違う。
perform_async は即実行対象として、すぐ通常のキューに積まれるperform_in は指定時間後に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移されるperform_at は指定日時に実行される予約ジョブとして保存され、時刻が来ると通常キューへ移されるperform_bulk は複数ジョブをまとめて Redis に投入するperform_inline / perform_sync は Redis のキューに積まず、現在のプロセスで即実行するキューを呼び出しごとに変えたい場合は set を使う。
WelcomeEmailJob.set(queue: :critical).perform_async(user.id)
| メソッド | 対象 | 挙動 |
|---|---|---|
perform |
共通 | 自分で定義する実処理。直接呼ぶより、ジョブ実行時に呼ばれる想定 |
perform_later |
ActiveJob | ジョブをキューへ登録する |
perform_now |
ActiveJob | キューに積まず、その場で perform を実行する |
set(wait: ...).perform_later |
ActiveJob | 指定時間後に実行する予約ジョブを登録する |
set(wait_until: ...).perform_later |
ActiveJob | 指定日時に実行する予約ジョブを登録する |
ActiveJob.perform_all_later |
ActiveJob | 複数の ActiveJob をまとめて登録する |
perform_async |
Sidekiq ネイティブ | ジョブを通常キューへ登録する |
perform_in |
Sidekiq ネイティブ | 指定時間後に実行する予約ジョブを登録する |
perform_at |
Sidekiq ネイティブ | 指定日時に実行する予約ジョブを登録する |
perform_bulk |
Sidekiq ネイティブ | 複数ジョブをまとめて登録する |
perform_inline |
Sidekiq ネイティブ | キューに積まず、その場で実行する |
perform_sync |
Sidekiq ネイティブ | perform_inline の alias |
WelcomeEmailJob.perform_later(user.id)
↓ ActiveJob が Sidekiq adapter に渡す
↓ 引数を Redis(キュー)に積む
↓ 呼び出し元は即座に次の処理へ進む
(後で Sidekiq ワーカーがキューを取り出し)
↓
def perform(user_id) ← perform_later に渡した引数が来る
...
end
Sidekiq ネイティブ API の場合は perform_later の代わりに perform_async を使う。
WelcomeEmailJob.perform_async(user.id)
↓ 引数を Redis(キュー)に積む
↓ 呼び出し元は即座に次の処理へ進む
(後で Sidekiq ワーカーがキューを取り出し)
↓
def perform(user_id) ← perform_async に渡した引数が来る
...
end
ルール:
perform_later は ActiveJob が提供するクラスメソッドperform_async は Sidekiq が提供するクラスメソッドperform は自分で定義するインスタンスメソッド。ここに処理を書くexecute など別名にはできないclass DataImportJob < ApplicationJob
retry_on StandardError, wait: 10.seconds, attempts: 3
def perform(file_path, user_id)
user = User.find(user_id)
process(file_path)
notify_success(user)
rescue StandardError => e
notify_failure(e, user) if user
raise # raise しないとリトライされない
end
end
rescue して例外を握りつぶすと、ジョブが成功した扱いになりリトライされないraise して例外を再送出するuser が nil になりうる場合(find 失敗時)は通知をスキップするsidekiq_options retry: 3 を使う重い処理を受け付けるエンドポイントとしてよく使われる。
class Mutations::ImportData < BaseMutation
field :success, Boolean, null: false
argument :file_path, String, required: true
# Mutation 実行前の権限チェック(ready? は必ず実行される)
def ready?(**_params)
raise ForbiddenError unless current_user.admin?
true
end
def resolve(file_path:)
# ジョブをキューに積んで即 success: true を返す
DataImportJob.perform_later(file_path, context[:current_user].id)
{ success: true }
end
end
ポイント:
resolve の中では重い処理を行わず、ジョブに委譲するDataImportJob が include Sidekiq::Job のクラスなら、ここは perform_async を使う| 処理 | 同期 or 非同期 |
|---|---|
| メール送信 | 非同期(ジョブ) |
| CSV インポート | 非同期(ジョブ) |
| 外部 API 呼び出し | 非同期(ジョブ) |
| 検索インデックスの更新 | 非同期(ジョブ) |
| バリデーション結果を即返す | 同期 |
| 単純な DB 読み書き | 同期 |