Background jobs with Sidekiq and ActiveJob

Sarah Mitchell Feb 2026
3 tabs
class UserNotificationJob < ApplicationJob
  queue_as :default

  # Retry up to 5 times with exponential backoff
  retry_on StandardError, wait: :exponentially_longer, attempts: 5

  # Discard job if user not found
  discard_on ActiveRecord::RecordNotFound

  def perform(user_id, notification_type, data = {})
    user = User.find(user_id)

    case notification_type
    when 'email'
      send_email_notification(user, data)
    when 'push'
      send_push_notification(user, data)
    when 'sms'
      send_sms_notification(user, data)
    end

    track_notification_sent(user, notification_type)
  end

  private

  def send_email_notification(user, data)
    UserMailer.notification(user, data).deliver_now
  end

  def send_push_notification(user, data)
    PushNotificationService.new(user).send(data[:message])
  end

  def send_sms_notification(user, data)
    TwilioService.send_sms(user.phone, data[:message])
  end

  def track_notification_sent(user, type)
    Analytics.track(
      user_id: user.id,
      event: 'notification_sent',
      properties: { type: type }
    )
  end
end

# Usage:
# Enqueue immediately
# UserNotificationJob.perform_later(user.id, 'email', { subject: 'Welcome!' })
#
# Enqueue with delay
# UserNotificationJob.set(wait: 1.hour).perform_later(user.id, 'email', data)
#
# Schedule for specific time
# UserNotificationJob.set(wait_until: Date.tomorrow.noon).perform_later(user.id, 'push', data)
3 files · ruby Explain with highlit

Sidekiq processes background jobs asynchronously using Redis and multi-threading. ActiveJob provides framework-agnostic interface—I use it for portability between job processors. Jobs handle emails, data processing, API calls, report generation. perform_later enqueues jobs; perform_now executes synchronously. I set priorities and queues for job organization. Retry logic with exponential backoff handles transient failures. Dead job queues capture permanent failures. Unique jobs prevent duplicates using sidekiq-unique-jobs gem. Scheduled jobs use set(wait:) or cron schedules. Batch processing groups related jobs. Monitoring via Sidekiq Web UI tracks throughput and failures. Proper job design—idempotent, atomic operations—ensures reliability. Background processing improves response times and user experience.