Solid Queue vs Sidekiq vs GoodJob: Rails Job Backend Trade-offs
Compare Solid Queue, Sidekiq, and GoodJob for Rails background jobs by workload shape: throughput, pickup latency, Redis cost, batch support, retry semantics, and migration risk.
Solid Queue is the default I would start with for ordinary Rails 8 jobs. Choose Sidekiq when sustained throughput, Redis-level pickup latency, or Sidekiq's paid features are real product requirements. Choose GoodJob when you want PostgreSQL-backed jobs but need lower pickup latency, batches, or uniqueness sooner than Solid Queue gives them. All three can sit behind Active Job, but switching later still means checking retries, recurring jobs, concurrency rules, and dashboards.
Solid Queue becoming the Rails 8 default changed the question from "which job gem do I install" to "do I have a reason to leave the default." Sometimes you do. Sidekiq still gives you the Redis-backed throughput ceiling. GoodJob ships features for free - batches, unique jobs - that Sidekiq puts behind a paid license. I've run all three in live Rails apps; the rest of this post is what each one costs operationally and where the default stops being the right answer.
Scope: feature coverage and prices in this post are date-sensitive; the comparison is written for Rails 8-era defaults and the job-backend feature surfaces described below. The benchmark is one synthetic workload on one VPS and should be used as a shape-of-the-trade-off datapoint rather than a sizing rule.
Solid Queue vs Sidekiq: Which Should You Use?
Pick Solid Queue for most Rails 8 apps - it ships built in, needs no Redis, and handles up to roughly 1,000 jobs per minute. Choose Sidekiq when you consistently process 2,000+ jobs per minute or need its Pro batches and rate limiting. GoodJob beats both when you want PostgreSQL-backed jobs with sub-second pickup and free batch callbacks.
The Comparison at a Glance
The table below is the fast version. The sections after it are where each backend becomes annoying in practice, which is the part a glance table cannot show.
| Solid Queue | Sidekiq | GoodJob | |
|---|---|---|---|
| Storage | PostgreSQL/MySQL | Redis | PostgreSQL |
| Throughput | ~800-1,200 jobs/min | ~5,000-10,000+ jobs/min | ~1,500-2,500 jobs/min |
| Job pickup latency | 100ms-5s (polling) | 5-15ms (push) | 50-200ms (LISTEN/NOTIFY) |
| Rails integration | Ships with Rails 8 | Separate gem | Separate gem |
| Active Job support | Native | Via adapter | Native |
| Recurring jobs | Built-in (recurring.yml) | Requires sidekiq-cron | Built-in (cron-style) |
| Concurrency control | Built-in (limits_concurrency) | Enterprise only ($) | Built-in (key-based) |
| Batch jobs | No | Pro/Enterprise ($) | Built-in |
| Dashboard | Mission Control (separate gem) | Sidekiq Web (included) | Built-in (included) |
| Unique jobs | Manual (DB locks) | Enterprise only ($) | Built-in |
| Extra infrastructure | None | Redis server | None |
| Monthly infra cost | $0 extra | $5-40 (managed Redis) | $0 extra |
| Maturity | Since 2023 | Since 2012 | Since 2020 |
| Retry handling | Active Job retry_on | Automatic (25 retries) | Active Job retry_on + auto |
This table captures the headline differences. The throughput and latency numbers are ballparks from the benchmark section, not vendor limits.
Solid Queue: The Rails Default
Solid Queue is the path of least resistance for Rails 8. It ships with the framework, requires zero additional infrastructure, and covers the common cases well.
What you get for free is the part that matters: zero-config setup in a new Rails 8 app, transactional enqueue (the job row and your data commit in the same transaction), recurring jobs via config/recurring.yml, and per-job concurrency through limits_concurrency, with Mission Control for monitoring. What you give up is pickup latency and a couple of features: polling means 100ms to a few seconds before a job starts, there is no batch support, and unique jobs are something you build with database locks. Those limits get their own section near the end. The short version is that none of them bite until job volume or user-facing latency makes them bite.
I covered Solid Queue setup in detail in the practical guide, so I won't repeat the installation here. The short version: bin/rails solid_queue:install, bin/rails db:prepare, tune config/queue.yml, and you're running.
Where Solid Queue Shines
Transactional enqueue is Solid Queue's strongest argument. When you create a record and enqueue a job in the same request, both happen in the same database transaction:
ActiveRecord::Base.transaction do
order = Order.create!(params)
# This INSERT goes into the same transaction
OrderConfirmationJob.perform_later(order.id)
end
# Both commit together, or neither does
With Sidekiq, the job enqueue goes to Redis - a separate system. If your app crashes between the database commit and the Redis write, the job can be lost unless you add an outbox-style pattern or another transactional boundary. With Solid Queue, the enqueue record can commit with the application data because both live in the database.
For e-commerce, SaaS billing, or any workflow where "job definitely fires after data saves" matters, this is a real advantage.
Sidekiq: The High-Throughput Option
Sidekiq dominated Rails background jobs for over a decade, and for good reason. Redis is fast, the ecosystem is enormous, and at high volume nothing else comes close.
What it does well:
- 5-10x throughput compared to database-backed alternatives
- Sub-15ms job pickup latency
- Proven at scale (millions of jobs/day)
- Rich Pro/Enterprise features (batches, rate limiting, unique jobs)
- Extensive middleware ecosystem
- Most tutorials and Stack Overflow answers assume Sidekiq
Where it falls short:
- Requires Redis infrastructure (though managed Upstash or Fly now start around $5-10/month)
- No transactional enqueue (separate datastore)
- Advanced features locked behind paid tiers (Pro is $995/year; Enterprise starts at $269/month, licensed per 100-thread pack)
- Jobs aren't durable by default (Redis persistence caveats)
- One more service to monitor, back up, and scale
Sidekiq 8.x: What Changed
If your mental model of Sidekiq is the 6.x or 7.x era, the 8.x line (current as of 2026) tightened a few things worth knowing before you adopt it:
- Newer runtimes required. Sidekiq 8 needs Ruby 3.2+ and Redis 7.0+ (the docs build against 7.2.x, but 7.0 is the floor). If you're pinned to an older Redis, you upgrade the datastore first.
- Redis-compatible backends are fine. Valkey and Dragonfly both work as drop-in replacements, which matters now that Redis changed its license - you're not locked into Redis Inc.'s offering.
- Capsules. Introduced in 7.0 and now standard, capsules let one Sidekiq process run multiple isolated thread pools with their own concurrency and queues. The embedding API also lets you run Sidekiq inside the Puma process for small apps, much like Solid Queue's Puma plugin.
- Built-in metrics and a reworked Web UI. The dashboard ships historical job metrics (latency, execution time) and in-app profiling, so you lean less on external APM for basic queue visibility.
None of this changes the core trade-off - you still run Redis, and batches/rate-limiting/unique-jobs still live in the paid tiers - but the operational story is smoother than the Sidekiq most older tutorials describe.
The Redis Question
The most common argument against Sidekiq in 2026 is the Redis dependency. Here's when that actually matters:
Redis is a real burden when:
- You're a solo developer or small team managing your own infrastructure
- You're deploying to a single VPS with Kamal
- You're already running PostgreSQL and don't want a second datastore (a second service to monitor, back up, and patch is the real cost now - managed Redis itself is cheap)
Redis is not a burden when:
- You're on a platform that bundles Redis (Heroku, Render)
- Your team already operates Redis for caching
- You need Redis for other features (ActionCable, rate limiting)
- You're at scale where the performance justifies the cost
If Redis is already in your stack for caching or ActionCable, adding Sidekiq is nearly free in operational terms. If your only Redis use would be Sidekiq, the calculus changes.
Sidekiq's Paid Tiers
Features you need to pay for:
| Feature | Sidekiq OSS (Free) | Sidekiq Pro ($995/yr) | Sidekiq Enterprise (from $269/mo, per 100 threads) |
|---|---|---|---|
| Basic job processing | Yes | Yes | Yes |
| Retries with backoff | Yes | Yes | Yes |
| Web dashboard | Yes | Yes | Yes |
| Batch jobs | No | Yes | Yes |
| Rate limiting | No | No | Yes |
| Unique jobs | No | No | Yes |
| Periodic jobs | No | No | Yes |
| Multi-process management | No | No | Yes |
| Rolling restarts | No | No | Yes |
Sidekiq Pro is $99/month or $995/year for unlimited usage, and Enterprise starts at $269/month per 100 threads with volume discounts. Those are the figures as of the last check; verify current pricing at sidekiq.org before quoting them.
Both Solid Queue and GoodJob include concurrency controls, recurring jobs, and unique job patterns for free. That's worth noting when comparing total cost of ownership.
GoodJob: The Overlooked PostgreSQL Option
GoodJob is the option most people skip past. In use since 2020, it uses PostgreSQL like Solid Queue but picks up jobs 10-25x faster through LISTEN/NOTIFY instead of polling.
What it does well:
- LISTEN/NOTIFY for near-real-time job pickup (50-200ms vs Solid Queue's 100ms-5s)
- Built-in batch support with callbacks
- Built-in unique jobs (key-based deduplication)
- Polished dashboard out of the box
- Cron-style scheduling with a DSL
- More mature than Solid Queue (3 years head start)
- Active community and responsive maintainer
Where it falls short:
- Not the Rails default (you're opting out of the blessed path)
- Smaller community than Sidekiq
- No MySQL support (PostgreSQL only)
- Slightly more configuration than Solid Queue's zero-config
- Less documentation and fewer tutorials than Sidekiq
The LISTEN/NOTIFY Advantage
The biggest technical difference between GoodJob and Solid Queue is how they detect new jobs.
Solid Queue polls your database at intervals:
# config/queue.yml
workers:
- queues: default
polling_interval: 1 # Check every 1 second
GoodJob uses PostgreSQL's LISTEN/NOTIFY:
# GoodJob listens for notifications on a PostgreSQL channel
# When a job is enqueued, the database notifies waiting workers immediately
# No polling interval - workers wake up within milliseconds
In practice, this means GoodJob picks up jobs in 50-200ms compared to Solid Queue's 100ms-5s. For most background jobs this difference is irrelevant - your email sends just fine either way. But for jobs that trigger visible UI updates or where users are waiting for something to happen, that 2-5 second gap in Solid Queue can feel sluggish.
GoodJob Setup
# Gemfile
gem "good_job"
# Install
bin/rails good_job:install
bin/rails db:migrate
# 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 # Run in web process
# Or :external for separate worker process
config.good_job.max_threads = 5
config.good_job.poll_interval = 30 # Fallback polling (LISTEN/NOTIFY is primary)
config.good_job.shutdown_timeout = 25
# Recurring jobs
config.good_job.enable_cron = true
config.good_job.cron = {
daily_cleanup: {
cron: "0 3 * * *", # 3am daily
class: "CleanupJob"
},
hourly_sync: {
cron: "0 * * * *", # Every hour
class: "ExternalSyncJob",
args: [{ full: false }]
}
}
end
GoodJob's Built-in Batches
This is a feature neither Solid Queue nor free Sidekiq offers:
# Create a batch of jobs with a callback when all complete
batch = GoodJob::Batch.enqueue(on_finish: BatchCallbackJob) do
users.each do |user|
GenerateReportJob.perform_later(user.id)
end
end
# BatchCallbackJob runs after ALL report jobs finish
class BatchCallbackJob < ApplicationJob
def perform(batch, params)
AdminMailer.all_reports_ready(batch.id).deliver_later
end
end
With Sidekiq, you need Pro ($995/year) for this. With Solid Queue, you'd need to build it yourself with a counter and a check-and-notify pattern.
GoodJob's Dashboard
GoodJob ships with a full dashboard - no separate gem needed:
# config/routes.rb
authenticate :user, ->(user) { user.admin? } do
mount GoodJob::Engine, at: "/good_job"
end
The dashboard includes real-time job monitoring, cron schedule visualization, batch tracking, error inspection with full backtraces, and performance graphs. It's more polished out of the box than Mission Control, the separate dashboard gem you bolt onto Solid Queue, which I walk through in the full Mission Control guide.
GoodJob vs Solid Queue
These two are the real decision for most teams, since both are PostgreSQL-backed and skip the Redis dependency entirely. The split comes down to integration versus features.
Solid Queue wins on being the default: it ships with Rails 8, the Rails core team maintains it, and future framework work will assume it. GoodJob wins on what's in the box today - LISTEN/NOTIFY pickup (50-200ms vs Solid Queue's 100ms-5s polling), batch callbacks, key-based unique jobs, and a more mature dashboard. Solid Queue also supports MySQL; GoodJob is PostgreSQL only.
| Solid Queue | GoodJob | |
|---|---|---|
| Job pickup | Polling (100ms-5s) | LISTEN/NOTIFY (50-200ms) |
| Throughput | ~800-1,200 jobs/min | ~1,500-2,500 jobs/min |
| Batch callbacks | Build it yourself | Built-in |
| Unique jobs | Manual (DB locks) | Built-in (key-based) |
| Database | PostgreSQL or MySQL | PostgreSQL only |
| Dashboard | Mission Control (separate gem) | Built-in |
| Maintained by | Rails core team | bensheldon + community |
My rule of thumb: start with Solid Queue on a new Rails 8 app and only move to GoodJob when you hit a concrete need it solves - batch workflows, sub-second pickup for user-facing jobs, or unique-job deduplication you'd otherwise hand-roll.
Migrating from GoodJob to Solid Queue
If you're already on GoodJob and want to consolidate on the Rails default, the move is incremental because both speak Active Job. Install Solid Queue alongside GoodJob (bin/rails solid_queue:install, run the migrations), then flip job classes over a few at a time with self.queue_adapter = :solid_queue while GoodJob keeps draining the rest. Rewrite GoodJob's cron schedule into config/recurring.yml, and replace GoodJob::Batch callbacks with a counter-and-check pattern or by keeping those specific workflows on GoodJob until you've built a replacement. Once the GoodJob tables are empty and no class points at :good_job, switch the global adapter and drop the gem.
Workload benchmark
On my test rig, Sidekiq processed this particular workload about 5x faster than Solid Queue and about 2.5x faster than GoodJob. I ran 10,000 lightweight jobs (JSON parse plus one DB write) against each backend, on a 4-core Hetzner VPS running Ubuntu 24.04, PostgreSQL 16, and Redis 7. Same database, same hardware, same workload, warm cache - only the queue adapter changed between runs.
| Metric | Solid Queue | Sidekiq | GoodJob |
|---|---|---|---|
| Total processing time | 9.2 min | 1.8 min | 4.5 min |
| Jobs per minute | ~1,090 | ~5,560 | ~2,220 |
| Avg job pickup latency | 1.2s | 8ms | 120ms |
| P99 job pickup latency | 4.8s | 45ms | 380ms |
| Memory usage (worker) | 180 MB | 210 MB | 195 MB |
| DB connections used | 12 | 2 (Redis) + 5 (PG) | 15 |
| CPU usage (worker) | 35% | 55% | 40% |
Important caveats:
- This is a single self-run synthetic benchmark, not a general one. Real jobs with heavier payloads, external API calls, or complex queries will shift the numbers
- Solid Queue polling was set to 1s. Lower intervals improve throughput but increase DB load
- GoodJob used async mode with 5 threads
- Sidekiq used 10 threads, 1 process
- All three shared the same PostgreSQL instance (so the database-backed queues competed with each other for connections on their own runs, not across runs)
What These Numbers Mean in Practice
If your app processes a few hundred lightweight jobs per minute at peak, all three are plausible. If you're at several thousand per minute on similar job shapes, Sidekiq pulls ahead meaningfully. GoodJob sits in the middle - faster than Solid Queue in this test, but not touching Sidekiq's throughput.
The latency difference matters more than raw throughput for most apps. If a user clicks "Export Report" and you enqueue a job, the difference between 8ms pickup (Sidekiq), 120ms pickup (GoodJob), and 1.2s pickup (Solid Queue) is the difference between "instant" and "noticeable pause."
Operating cost comparison
Monthly infrastructure cost for a typical SaaS application on a VPS, excluding application server costs.
| Solid Queue | Sidekiq (OSS) | Sidekiq Pro | GoodJob | |
|---|---|---|---|---|
| Redis (managed) | $0 | $5-40/mo | $5-40/mo | $0 |
| Redis (self-hosted) | $0 | $40/mo (VPS) | $40/mo (VPS) | $0 |
| License | Free | Free | $83/mo ($995/yr) | Free |
| Extra DB load | Low | None | None | Medium |
| Total (managed) | $0 | $5-40 | $88-123 | $0 |
| Total (self-hosted) | $0 | $40 | $123 | $0 |
Managed Redis is no longer the line item it used to be. Upstash bills per-request and starts near $0 for low volume, and Fly's managed offering runs roughly $5-40/month depending on memory - a far cry from the $95+/month a dedicated managed Redis cost a few years ago. The Sidekiq cost that still bites is the Pro/Enterprise license, not the datastore.
Over a year, managed Sidekiq Pro runs roughly $1,050-1,500 more than Solid Queue or GoodJob, and almost all of that is now the $995 license rather than infrastructure. That's still real money for a bootstrapped SaaS.
The hidden cost with database-backed queues is increased PostgreSQL load. With heavy job volume, you might need a larger database instance. But for most applications, the existing database handles it without issue.
Feature Matrix: What Ships Free
The free tier comparison matters because most teams start there.
| Feature | Solid Queue | Sidekiq OSS | GoodJob |
|---|---|---|---|
| Active Job native | Yes | Via adapter | Yes |
| Recurring/cron jobs | Yes | No (need gem) | Yes |
| Concurrency controls | Yes | No | Yes |
| Unique jobs | No | No | Yes |
| Batch jobs | No | No | Yes |
| Job prioritization | Yes (queue-based) | Yes (queue weights) | Yes (priority column) |
| Dashboard | Separate gem | Included | Included |
| Transactional enqueue | Yes | No | Yes |
| Multi-queue workers | Yes | Yes | Yes |
| Graceful shutdown | Yes | Yes | Yes |
| Separate worker process | Yes | Yes | Yes |
| In-process mode | Yes (Puma plugin) | No | Yes (async mode) |
GoodJob wins the free feature comparison. Solid Queue wins on Rails integration. Sidekiq wins on raw performance and ecosystem size.
Open-Source Alternatives to Sidekiq (and Sidekiq Pro)
You can replace almost every paid Sidekiq Pro and Enterprise feature with a free, open-source equivalent. Solid Queue and GoodJob cover most of the gap natively, and a few small gems fill the rest. Here is how each commercial feature maps to a free option for a Rails app.
| Sidekiq Pro/Enterprise feature | Free alternative | Note |
|---|---|---|
| Batches (Pro) | GoodJob::Batch, or Active Job callbacks | GoodJob ships batch callbacks free; Solid Queue needs a counter-and-check pattern |
| Rate limiting (Enterprise) | Solid Queue limits_concurrency, GoodJob throttling, or the sidekiq-throttled gem | Concurrency limits cap how many jobs run at once without a paid tier |
| Unique jobs (Enterprise) | GoodJob key-based uniqueness, or the activejob-uniqueness gem | Deduplicate by an argument key before enqueue or before execution |
| Expiring jobs (Enterprise) | discard_on, or a perform-time TTL guard | Drop stale jobs by comparing enqueued_at against a cutoff inside perform |
| Encryption (Enterprise) | Active Record Encryption on job arguments, or the concurrent-ruby toolkit for guarded payloads | Encrypt sensitive fields before they land in the queue table |
| Periodic/cron jobs (Enterprise) | Solid Queue recurring.yml, GoodJob cron, or the sidekiq-cron gem | All three are free; only stock Sidekiq lacks built-in scheduling |
| Web dashboard | Mission Control (Solid Queue), GoodJob dashboard | Both PostgreSQL backends include a dashboard at no cost |
For most teams the realistic move is not buying Sidekiq Pro - it is switching to a PostgreSQL-backed queue that bundles these features. GoodJob in particular covers batches, unique jobs, and concurrency without a license. Just confirm the alternative actually matches your semantics: GoodJob's batch callbacks behave differently from Sidekiq's, and reproducing them on Solid Queue is an architecture decision, not just a code-organization choice, so design where that logic lives before you swap backends.
Decision Framework
After running all three in real apps, here's the framework I use.
Choose Solid Queue When
- You're building a new Rails 8 app and want the simplest path
- Your job volume is under 1,000 per minute
- You value convention over configuration (the Rails way)
- Transactional enqueue is important for data integrity
- You're deploying to a single VPS and want minimal infrastructure
- Your team is small and ops simplicity is a priority
Typical fit: Early-stage SaaS, internal tools, MVPs, solo developer projects, small team apps.
Choose Sidekiq When
- You process more than 2,000 jobs per minute consistently
- Job pickup latency under 50ms matters for your use case
- You need Pro/Enterprise features (batches, rate limiting, unique jobs)
- Redis is already in your stack for caching or ActionCable
- You're at scale where the performance gap justifies the cost
- Your team has experience operating Redis
Typical fit: High-traffic e-commerce, large B2B platforms, data processing pipelines, apps with real-time job requirements.
Choose GoodJob When
- You want PostgreSQL-backed jobs but need better latency than Solid Queue
- Batch jobs with callbacks are a core requirement
- You need built-in unique jobs without building it yourself
- You prefer a PostgreSQL option that has had years under real workloads to shake out edge cases
- The polished dashboard matters for your operations team
- You want the features of Sidekiq Pro without the cost
Typical fit: Mid-stage SaaS, apps with batch workflows (report generation, bulk operations), teams that want PostgreSQL simplicity with richer features than Solid Queue.
The Hybrid Approach
You're not locked into one. Rails makes it easy to mix backends per job:
# Most jobs use the default (Solid Queue or GoodJob)
class ApplicationJob < ActiveJob::Base
# Uses config.active_job.queue_adapter
end
# High-throughput jobs use Sidekiq
class EventTrackingJob < ApplicationJob
self.queue_adapter = :sidekiq
queue_as :firehose
def perform(event_data)
Analytics.track(event_data)
end
end
# Everything else stays on the default
class WelcomeEmailJob < ApplicationJob
queue_as :mailers
def perform(user_id)
UserMailer.welcome(user_id).deliver_now
end
end
I've used this pattern in live systems: Solid Queue for 90% of jobs, Sidekiq for the high-volume analytics queue. The operational overhead of running both is modest if Redis is already in the stack.
Migration Paths
Moving Between Backends
All three support Active Job, so switching is mostly configuration:
# Switch globally
config.active_job.queue_adapter = :good_job # or :sidekiq, :solid_queue
# Switch per-job during migration
class SomeJob < ApplicationJob
self.queue_adapter = :good_job
end
The real migration work is in:
- Retry semantics - Sidekiq retries automatically; Solid Queue and GoodJob rely on Active Job's
retry_on - Recurring jobs - Each backend has its own format
- Concurrency controls - Different APIs and mental models
- Monitoring - Different dashboards and metrics
I wrote a detailed Sidekiq to Solid Queue migration guide that covers the per-job rollout strategy. The same incremental approach works for any backend switch.
Trade-offs and Limitations
Solid Queue Limitations
- Polling overhead on the database: Each poll is a query. With aggressive polling intervals and many workers, this adds load to your primary database. A separate queue database mitigates this but adds complexity
- No LISTEN/NOTIFY: Jobs sit in the database until the next poll cycle. Minimum practical latency is 100ms, typical is 1-3 seconds
- Young ecosystem: Fewer blog posts, tutorials, and Stack Overflow answers. When you hit an edge case, you're reading source code
- Missing batch support: If your workflow needs "run these 50 jobs, then do X when all finish," you'll build it yourself
Sidekiq Limitations
- Redis is a single point of failure: If Redis goes down, your jobs stop. Redis persistence helps but adds operational complexity
- No transactional enqueue: Jobs enqueued to Redis can be lost if the app crashes between the database commit and the Redis write
- Feature gatekeeping: Concurrency controls, unique jobs, and batches require paid tiers. These are free in the PostgreSQL alternatives
- Memory-bound scaling: Redis keeps everything in memory. Large job payloads or deep backlogs consume expensive RAM
GoodJob Limitations
- Not the Rails default: You're stepping off the standard path. Future Rails upgrades might favor Solid Queue's integration patterns
- PostgreSQL only: No MySQL support. If you're on MySQL, GoodJob isn't an option
- Smaller community: Fewer contributors and users than Sidekiq means slower bug fixes for edge cases
- LISTEN/NOTIFY scaling: Under extreme load (10,000+ notifications/second), PostgreSQL's LISTEN/NOTIFY can become a bottleneck. At that point, you need Sidekiq anyway
When None of These Work
If you're processing 50,000+ jobs per minute with strict ordering guarantees, look at dedicated message brokers: Kafka, RabbitMQ, or AWS SQS. These aren't Rails job backends - they're infrastructure-level solutions for a different class of problem.
What I'd actually reach for
For a new Rails 8 app I start with Solid Queue and do not think about it again until job volume or latency forces the question. Most apps run well under 1,000 jobs per minute, and at that volume the real choice is between Solid Queue's zero-config integration and GoodJob's richer free features. If a project has batch workflows on day one, I reach for GoodJob directly rather than hand-rolling a counter-and-check pattern on Solid Queue.
Sidekiq enters the picture in two cases: sustained volume past a couple thousand jobs per minute, or Redis already sitting in the stack doing other work. When neither is true, paying for Redis (and possibly a Pro license) to get features the PostgreSQL backends ship free is a hard sell.
Whichever you pick, keep your jobs on Active Job's API instead of backend-specific classes. That is what makes this a reversible decision: switching adapters later is configuration, not a rewrite.
If the queue backend decision is still unclear after the table, I would inspect the job mix rather than the gem names: peak jobs per minute, pickup-latency requirements, retry behavior, recurring schedules, and which Sidekiq features are actually in use. I help teams do that review through background job architecture work.
Further Reading
- Solid Queue in Rails 8: Setup, Recurring Jobs, and Config
- Solid Queue recurring and cron jobs - cron syntax, schedules, and idempotent recurring jobs
- Sidekiq to Solid Queue: Zero-Downtime Migration Guide
- Deploy Rails 8 with Kamal to a VPS
- Database Optimization Techniques in Rails
- Rails AI Agents with the Anthropic SDK - A no-framework approach to running Claude-powered agents in Rails
- Building AI Agents in Ruby with the Gemini API - Wiring Gemini's Interactions API into Ruby without an SDK
- Solid Queue GitHub Repository
- GoodJob GitHub Repository
- Sidekiq GitHub Repository