Scaling Rails Applications with Background Jobs: Practical Patterns
When a Rails app grows beyond a few thousand daily users, synchronous request‑response cycles start to choke. Offloading work to background jobs not only improves perceived performance but also protects your database from overload. Below are three battle‑tested patterns we use at developerz.ai to keep Rails services responsive at scale.
1. Use find_each for Batch Processing
Rails’ find_each loads records in batches (default 1000) and yields them one at a time, preventing memory bloat. Combine it with a background worker:
class BulkEmailWorker < ApplicationJob
queue_as :default
def perform(user_ids)
User.where(id: user_ids).find_each(batch_size: 500) do |user|
UserMailer.welcome(user).deliver_later
end
end
end
This ensures only a handful of User objects live in memory at any moment.
2. Leverage ActiveJob’s set(wait:) for Rate‑Limited APIs
External APIs often impose rate limits. Scheduling jobs with a delay spreads the load:
User.where(active: true).find_each do |user|
SyncExternalProfileJob.set(wait: rand(1..5).minutes).perform_later(user.id)
end
The random wait avoids thundering‑herd spikes and keeps your API keys safe.
3. Partition Work with Sidekiq Queues
Separate critical from non‑critical work by assigning different queues:
:queues:
- critical
- default
- low_priority
Critical jobs (e.g., payment processing) go to the critical queue, guaranteeing they’re pulled first. Low‑priority tasks such as analytics aggregation can sit in low_priority and be processed when the system is idle.
Putting It All Together
A typical flow looks like this:
- Controller receives a request and enqueues a job.
-
Job uses
find_eachto process records in batches. - Sidekiq routes the job to the appropriate queue.
-
Rate‑limited external calls get scheduled with
set(wait:).
By following these patterns, you’ll see a measurable reduction in request latency and a more predictable memory footprint.
Ready to refactor your Rails stack? Reach out at developerz.ai for a code review or a custom implementation.
Top comments (0)