Sidekiq Alternatives for Webhook Retries: Hookdeck Event Gateway, Solid Queue, GoodJob, and Cloud Queues Compared
Sidekiq is so embedded in Rails that it becomes the default tool for "webhook retries" the moment a controller action starts seeing 5xx responses or a Stripe rate limit. Move the work into a Sidekiq::Job, call perform_async from the controller, and you have something that looks like webhook resilience, with Sidekiq's generous default retry schedule (25 attempts over roughly three weeks) doing the backoff for you.
This works well enough for a while, but pretty soon Redis becomes a critical-path service you operate. Signature verification ends up being copy-pasted in every webhook controller. Webhook storms hit Puma before they hit Redis so your application becomes the throttle. And when a payload exhausts its retries and lands in the Dead set, you have a Sidekiq job (not a webhook record), and you're left matching the Sidekiq Web UI with Stripe's dashboard to figure out what happened.
In this article, we'll look at the pros and cons of using Sidekiq for webhook retries and compare it with alternatives: Hookdeck Event Gateway, Solid Queue, GoodJob, cloud queues like AWS SQS, and Convoy. Working in a different stack? See the equivalent guides for Celery in Python and BullMQ in Node.
How to evaluate a Sidekiq alternative for webhook retries
Comparing Sidekiq alternatives is tricky because they don't all sit in the same place in the stack. Solid Queue and GoodJob are like-for-like Rails job backends. Hookdeck and Convoy are webhook gateways that sit in front of your application. SQS is a cloud primitive you wire up yourself. So we'll compare them on the things that actually matter when retries are on the line:
Webhook-aware semantics: Does the tool understand signatures, idempotency keys, and source identity, or does that logic live in your Ruby code?
Failed-payload visibility: When a retry exhausts, do you see the original webhook (headers, body, timestamps) or just a job in the Dead set?
Per-source retry policy: Can you configure "Stripe retries for 7 days, Shopify retries for 1 hour" without code changes?
Operational footprint: Do you run Redis, a Sidekiq process, an autoscaler, and the monitoring around all of it?
Rails ecosystem fit: Does the alternative require a rewrite of your handler, or does it sit upstream and let your existing controller stay as-is?
Cost: Including hidden Redis cost, worker compute, the Sidekiq Pro/Enterprise license if you rely on its features, and the engineering hours spent maintaining the pipeline.
What Sidekiq does (and why Rails developers reach for it on webhooks)
Sidekiq is a Redis-backed background job processor for Ruby. You define a job class, enqueue it with perform_async, and Sidekiq's multi-threaded process pulls and runs it. It's been the default async-work tool in Rails for over a decade, integrates with Active Job, and ships with a built-in retry mechanism and a Web UI. Sidekiq Pro and Enterprise add batches, rate limiting, unique jobs, and more.
Sidekiq key features
- Redis-backed queue: Jobs are serialized to Redis; a multi-threaded worker process pulls and executes them.
- Built-in retries: By default, failed jobs retry up to 25 times with an exponential-ish backoff schedule spanning about three weeks, then move to the Dead set.
- Active Job integration: Drop-in backend for Rails'
ActiveJob, or useSidekiq::Jobdirectly for full control. - Web UI: A mountable dashboard showing queues, retries, scheduled jobs, and the Dead set.
- Pro/Enterprise features: Batches, unique jobs, rate limiting, and reliability guarantees behind a paid license.
Why Sidekiq gets used for webhook retries
It's already in the stack. If your Rails app has any background work, Sidekiq is probably handling it. Adding webhook retries means enqueuing a job from the controller, so no new service, no new dependency, no review meeting. And Sidekiq's default retry schedule is good enough that "webhook retries" feels solved the moment you call perform_async.
Where Sidekiq starts to hurt in a webhook context
The ack-before-enqueue gap. The standard Rails pattern is: controller verifies the signature, calls WebhookJob.perform_async(payload), and renders head :ok. If the process crashes or Redis is unreachable between those two lines, the webhook is gone. Sidekiq never sees it because it never arrived.
Signature verification redundantly coded per provider. Stripe HMAC-SHA256 in one controller, Shopify HMAC-SHA256 in another, GitHub HMAC-SHA1 in a third. Each implementation is a security surface and a source of subtle bugs (raw-body access before Rails parses it, timing-safe comparison, header naming). See how to implement SHA256 webhook signature verification for what this involves per provider.
Webhook spikes hit Puma, not Redis. When Stripe sends 5,000 events in 30 seconds during a promotion, your Puma workers are the first to feel it, Redis only sees what makes it past the request cycle. Sidekiq doesn't smooth the spike; it receives whatever survived. See how to protect your server from crashing during webhook spikes for what this looks like in practice.
Heroku H12 timeouts. Requests that take longer than 30 seconds get killed with an H12. If perform_async blocks on a slow Redis connection, the webhook 503s and the provider retries, duplicating work.
Visibility through a job lens, not a webhook lens. The Sidekiq Web UI shows you jobs, not webhooks. When retries exhaust, you have an entry in the Dead set with a backtrace but no record showing the original payload, the headers, the source provider, or the full retry trail correlated to the provider's delivery.
Retry policy is global and code-defined. Sidekiq's schedule is uniform across job classes unless you override sidekiq_retry_in in code. Changing "Stripe retries for 7 days, GitHub retries for 1 hour" means editing and deploying Ruby. For what good per-source retry behaviour looks like, see webhook retry best practices.
Sidekiq alternatives for webhook retries
If you're rethinking webhook retries, here are the alternatives we'll cover:
- Hookdeck Event Gateway: Managed webhook infrastructure that sits in front of your Rails controller, providing signature verification, durable queue, per-source retry policies, replay, and observability without a Redis instance to operate.
- Solid Queue and GoodJob: Database-backed Rails job backends if you want to stay inside Active Job but drop the Redis dependency.
- AWS SQS: A cloud-native queue (often via Shoryuken) that trades Redis ops for IAM and queue config.
- Convoy: Open-source self-hosted webhook gateway.
Hookdeck Event Gateway
Hookdeck Event Gateway takes a different architectural position to Sidekiq: it sits in front of your Rails app rather than behind it. The webhook reaches Event Gateway first, gets verified against the source's signing secret, gets deduplicated, and is held in a durable queue. Event Gateway then delivers it to your controller at a rate the application can handle, and retries per source, with the policy you configured, when delivery fails. Your controller becomes a thin endpoint that processes events Event Gateway has already handled the operational concerns for.
Hookdeck Event Gateway key features
- 120+ pre-configured sources: Stripe, Shopify, GitHub, Twilio, and the rest ship with signature verification handled, so no HMAC code in your controllers.
- Per-connection retry policy: Configure exponential, linear, or custom intervals; choose max-attempts, until-success, or a time-bounded window. Tune per source, no deploy.
- Failed-payload visibility: Issues capture the full original webhook (headers, body, query, timestamp) alongside the retry trail. Full-text search across event history.
- JavaScript transformations: In-flight enrichment via the Transformations editor, so no controller changes for shape adjustments.
- No Redis for you to operate: Durable queue, backpressure, and worker scaling are managed.
- Local development with the CLI:
hookdeck listen 3000proxies to a Rails server running locally with no ngrok required, and the same source configuration works in CI and production. - Free tier: Developer plan is $0/month with 10,000 events. Team plan starts at $39/month with a 99.999% uptime SLA.
How does Hookdeck Event Gateway compare to Sidekiq?
Hookdeck's Event Gateway moves the webhook concerns out of your application code and out of your operational surface. The controller stays idiomatic Rails, but it does less. Signature verification, queueing, retries, and observability all happen upstream of routes.rb.
The trade-off is that you're moving a responsibility from infrastructure you operate to a service you pay for. If your webhook volume is small and your team has bandwidth to maintain Sidekiq and Redis, the savings may not justify the line item. If webhooks are causing pages, missed events, or hours of debugging, the calculation changes quickly.
| Capability | Hookdeck Event Gateway | Sidekiq |
|---|---|---|
| Webhook-aware ingestion (signature, idempotency) | ✅ 120+ sources pre-configured | ❌ Hand-rolled per source |
| Per-source retry policy without code changes | ✅ Per-connection config | ❌ Code-defined |
| Failed-payload visibility | ✅ Issues + full-text search | ℹ️ Web UI + manual logs |
| Replay individual events | ✅ One-click | ℹ️ Manual retry from the Dead set |
| Redis / worker operations | ✅ Managed | ❌ You run Redis + Sidekiq processes |
| Local development | ✅ Via hookdeck listen | ℹ️ Plus ngrok and Redis locally |
| Self-hostable | ❌ | ✅ |
| Suits non-webhook background work | ❌ | ✅ Mailers, batches, scheduled jobs |
Try Hookdeck Event Gateway free
Webhook ingestion, durable queueing, and per-source retries without operating Redis
Solid Queue and GoodJob
Solid Queue is the database-backed Active Job backend that ships as the default in Rails 8. GoodJob is a mature Postgres-backed alternative with a built-in dashboard. Both let you drop Redis and keep your jobs in the same database as your business data, fewer moving parts, transactional enqueues.
For background work, both are excellent and increasingly the default choice for new Rails apps. For webhook retries specifically, they don't change the underlying problem: you still run a worker, still hand-roll signature verification, still have an ack-before-enqueue gap, and still inspect failed work through a job lens rather than a webhook one. They're the right answer if your goal is "drop Redis" rather than "stop owning the webhook boundary."
AWS SQS
Pushing webhook retries to SQS, typically via Shoryuken or Active Job's SQS adapter, trades Redis operations for IAM, queue config, and visibility tooling.
This shifts the operational burden but doesn't close the webhook-specific gaps. Signature verification still lives in your consumer. Idempotency keys still need a deduplication store. Per-source retry policy still requires multiple queues with different DLQ configs. Replay still means writing tooling on top of CloudWatch and the SQS console. For a deeper look, see AWS SQS alternatives for webhooks.
Convoy
Convoy is an open-source self-hosted webhook gateway. It's the closest like-for-like to Hookdeck Event Gateway for webhooks, but open-source.
The trade-offs are a smaller pre-configured source library, a less mature observability stack (no full-text search across event history, no integrated alerting equivalent to Issues), and you operate it yourself, Postgres, Redis, the Convoy service, and any metrics tooling. It's a good option when self-hosting is a hard requirement. For a deeper look, see the comparison of webhook gateway solutions.
When to keep Sidekiq
Sidekiq is still the right answer in several scenarios:
- Webhooks are a small fraction of an established Sidekiq footprint. If most of your queue is non-webhook work (mailers, exports, scheduled jobs), the savings of moving them out aren't worth fragmenting the stack.
- Self-hosting is mandatory. Compliance, data residency, or air-gapped deployments rule out a managed service. Sidekiq + Redis is well-understood.
- You rely on Sidekiq Pro/Enterprise features alongside webhook work. If batches, unique jobs, or reliability features share a worker pool by design, splitting them complicates ops more than it saves.
- Webhook volume is low and stable. No spikes, no rate limit pressure, no provider with aggressive retry policies. Sidekiq's default retry schedule is fine, you have other things to work on.
The migration argument gets stronger when webhook volume grows, when more providers come online, when on-call gets paged for webhook-related incidents, or when "what payload caused this?" becomes a recurring question.
Migrating Rails webhook retries to Hookdeck Event Gateway
The shape of the migration is small. The architectural diff:
Before:
flowchart LR
A[Stripe] --> B[Rails controller<br/>signature verification + retry policy in code]
B --> C[WebhookJob.perform_async]
C --> D[Sidekiq]
D --> E[Handler logic]
After:
flowchart LR
A[Stripe] --> B[Hookdeck<br/>signature verification + retry policy as config]
B --> C[Rails controller]
C --> D[Handler logic]
The steps:
- Create a Hookdeck source for Stripe (or whichever provider). Hookdeck generates a webhook URL and handles signature verification automatically.
- Create a connection from the source to your Rails endpoint. Configure the retry policy on the connection, exponential backoff, max attempts, retry window.
- Update the webhook URL in the provider dashboard to point at Hookdeck Event Gateway. Run in shadow alongside the existing Sidekiq path for a few days.
- Remove the
perform_asynccall from the webhook controller. The action now processes events synchronously, which Event Gateway has already verified, deduplicated, and queued. - Keep Sidekiq for everything else.
For the broader pattern, see managed webhook gateway vs DIY queue-backed infrastructure.
Hookdeck Event Gateway is the managed answer for webhook retries
Sidekiq isn't broken, it's just not purpose-built for webhooks, and the gap is felt every time there's an events spike, a Heroku H12, or a missing signature lands in your incident channel. The Rails ecosystem has been working around that gap for years with custom sidekiq_retry_in blocks, dedupe stores, raw-body controllers, and careful Redis tuning.
Hookdeck Event Gateway is managed webhook infrastructure that takes the work out of the Rails application. Signature verification, durable queueing, per-source retry policies, replay, and observability happen upstream of your controllers. Your action stays simple. Sidekiq stays for what it's actually good at (mailers, exports, scheduled jobs, non-webhook background work).
If you're testing this from a local Rails server, run hookdeck listen 3000 to forward webhooks to localhost, no ngrok required, and the same source configuration works in CI and production.
Try Hookdeck Event Gateway for free
Webhook ingestion, durable queueing, retries, and observability, without operating Sidekiq or Redis
FAQs
What is the best alternative to Sidekiq for webhook retries?
It depends on your priorities. If you want to stop running Redis and a worker pool and want webhook-aware retries with per-source policies and full payload visibility, Hookdeck Event Gateway is the strongest fit — it sits in front of your Rails controller rather than behind it. If you want to stay inside Active Job but drop the Redis dependency, Solid Queue (the Rails 8 default) or GoodJob give you a Postgres-backed alternative. If self-hosting is non-negotiable, Convoy is the open-source option.
Can I keep Sidekiq for background jobs and use something else just for webhook retries?
Yes — and this is the most common pattern. Sidekiq stays in the stack for mailers, exports, and scheduled jobs; webhook ingestion and retries move upstream to a dedicated webhook gateway like Hookdeck Event Gateway. Your Rails controller receives events that have already been verified, deduplicated, and queued, so the perform_async call for webhook work disappears.
Isn't Sidekiq's default retry schedule already good for webhooks?
Sidekiq's 25-attempt schedule is genuinely good backoff, but backoff is only one piece of webhook retries. It doesn't verify provider signatures, doesn't deduplicate, doesn't let you set different retry windows per provider without code, and when a job lands in the Dead set you see a Ruby backtrace rather than the original webhook correlated to the provider's delivery. A webhook gateway handles those concerns that a job retry schedule was never designed for.
Why not just use Sidekiq for webhook retries?
It works, but it leaves three problems unsolved. First, your application has to ack the webhook before the job hits Redis — events can be lost in that gap. Second, signature verification, idempotency, and source-specific retry policy live in your code, copy-pasted per provider. Third, when a retry fails, you have a Sidekiq job in the Dead set, not a webhook record — debugging means correlating the Web UI with provider logs. A webhook gateway moves all three concerns out of application code.
Does Hookdeck Event Gateway replace Redis if I move webhook retries off Sidekiq?
For the webhook half of the workload, yes. Hookdeck Event Gateway provides durable queueing, retries, and dead-letter behavior as a managed service, so you don't need Redis for webhook ingestion. Most teams keep Redis and Sidekiq for non-webhook background work (mailers, exports, scheduled jobs) and let Event Gateway own the webhook boundary.