DEV Community

Cover image for You Don't Need Sidekiq Pro for Batch Jobs, Rate Limiting, or Cron Here's a Free Drop-In
Muhammad Awais
Muhammad Awais

Posted on

You Don't Need Sidekiq Pro for Batch Jobs, Rate Limiting, or Cron Here's a Free Drop-In

If you've built anything non-trivial with Sidekiq, you've probably hit the wall where the feature you actually need batch job callbacks, rate limiting,scheduled jobs lives behind Sidekiq Pro or Enterprise. That's a reasonable business model, and it's funded years of full-time development on Sidekiq. If your company can afford the license, it's worth paying for. But a lot of teams can't justify the line item for a side project or an early startup. So I want to show what those features actually look like, and then show
a free, MIT-licensed, wire-compatible way to get them: wurk.

GitHub logo developerz-ai / wurk

Drop-in replacement for Sidekiq + Pro + Enterprise. 100% API-compatible, free forever, meaningfully faster. Mountable Rails engine.

Wurk β€” an orc ready to work

Wurk ⚑

Wurk, wurk. πŸͺ“ Ready to work. Zug zug.

A 100% drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise. Free forever.

Live Demo Gem Version CI Coverage gate Ruby License: MIT

Wurk is wire-compatible with Sidekiq β€” same Redis keys, same job JSON, same Ruby DSL. Swap one line in your Gemfile and your existing jobs, batches, limiters, cron entries, and live Redis data keep working untouched. The Pro and Enterprise feature sets ship in the same free gem, with no license check and no tiers.

On speed: Wurk is not currently faster than stock Sidekiq β€” it runs at roughly 0.87×–1.02Γ— depending on workload shape, with parity on CPU and I/O but still behind on framework overhead (noop) and boot time. Numbers, method, and the reproduction command are in docs/benchmarks.md; run them yourself with rake bench:vs_sidekiq.

Install

# Gemfile
gem "wurk"
Enter fullscreen mode Exit fullscreen mode
# ...or drop in over an existing Sidekiq stack β€” delete these, add
…
Enter fullscreen mode Exit fullscreen mode

The migration is one line

Wurk speaks the same Redis protocol as Sidekiq same keys, same job JSON, same
Ruby DSL. If you're already on Sidekiq:

- gem "sidekiq"
- gem "sidekiq-pro", source: "https://gems.contribsys.com/"
- gem "sidekiq-ent", source: "https://enterprise.contribsys.com/"
+ gem "wurk"
Enter fullscreen mode Exit fullscreen mode

bundle install, restart, done. Sidekiq::Worker, Sidekiq.configure_server,
your existing job classes β€” none of it changes. Your in-flight Redis data keeps
working untouched.

Batches, without the license check

Sidekiq::Batch lets you fire off a group of jobs and run a callback when the
whole group finishes β€” the classic use case is "process these 500 records, then
send one summary email."

batch = Sidekiq::Batch.new
batch.description = "Import customer CSV"
batch.on(:success, MyCallback, "to" => "ops@example.com")

batch.jobs do
  rows.each { |row| ImportRowJob.perform_async(row.id) }
end
Enter fullscreen mode Exit fullscreen mode

Batches nest, too β€” a parent batch's callback only fires once every child batch
has finished, which is what you want for multi-stage pipelines. In stock
Sidekiq this whole API is Pro-only. In wurk it's just... there.

Rate limiting five different ways

Sidekiq::Limiter β€” an Enterprise feature β€” ships five limiter types, because
"rate limit" means different things depending on what you're protecting:

# concurrent: at most N jobs of this type running at once
limiter = Sidekiq::Limiter.concurrent("api-calls", 10)

# window: at most N calls per rolling time window
limiter = Sidekiq::Limiter.window("api-calls", 100, 1.hour)

# leaky bucket, bucket, and points limiters cover the rest β€”
# see docs/rate-limiting.md for when to reach for which
limiter.within_limit do
  ThirdPartyApi.call
end
Enter fullscreen mode Exit fullscreen mode

If you've ever hand-rolled a Redis INCR + EXPIRE rate limiter and hit an
edge case at 2am, this is the version that's already handled the edge cases.

Cron jobs that actually run once

Periodic jobs are the other Enterprise feature, and the part that's easy to get
wrong yourself: if you run multiple worker processes, a naive cron
implementation fires the job once per process, not once total.

Sidekiq::Periodic.register("0 9 * * *", DailyReportJob)
Enter fullscreen mode Exit fullscreen mode

Wurk's periodic scheduler is leader-elected across the cluster, so this fires
exactly once regardless of how many worker processes you're running.

Encrypted job arguments

If a job argument is a customer's SSN, an API secret, or anything else you'd
rather not sit in plaintext in Redis or your logs, Enterprise's answer is
transparent AES-256-GCM encryption with key rotation:

class ChargeCardJob
  include Sidekiq::Job
  sidekiq_options encrypt: true
end
Enter fullscreen mode Exit fullscreen mode

The argument is encrypted before it hits Redis and decrypted only inside the
worker process. Wurk implements the same interface.

The dashboard, without a Node build

Wurk's Web UI mounts as a Rails engine, and the frontend ships precompiled
inside the gem β€” installing it doesn't pull Node into your build pipeline:

# config/routes.rb
authenticate :user, ->(u) { u.admin? } do
  mount Wurk::Engine => "/wurk"
end
Enter fullscreen mode Exit fullscreen mode

There's a live, read-only demo if you want to poke at it before installing
anything: wurk.demo.developerz.ai

How this is built

The honest context, because it's relevant if you're deciding whether to trust
this in your stack: wurk is built and maintained largely by AI agents, working
under human review, against a documented parity spec of Sidekiq's public API
(what we call a clean-room implementation β€” the interface, not the source).
There's a β‰₯90% line coverage gate enforced in CI, and the parity specs
themselves are written against Sidekiq's own documented OSS/Pro/Enterprise
surface, so behavior drift shows up as a failing test regardless of who wrote
the code.

It's new one production app running on it internally so far, plus the public
demo. I'm not going to oversell that. If you run Sidekiq at real scale and want
to try wurk against a staging environment, I'd genuinely like to know what breaks.

Repo: https://github.com/developerz-ai/wurk
Docs: https://developerz-ai.github.io/wurk/

What would stop you from trying this β€” licensing worry, missing feature,
something else? Curious to hear in the comments.

Top comments (2)

Collapse
 
swapnoneel123 profile image
Swapnoneel Saha

the wire compatibility and honest benchmark context make this easier to evaluate. i would add a migration checklist for redis data, job retry behavior, batch callbacks, scheduler leadership, and encryption key rotation, then run it in staging with duplicate and failover tests. exactly once scheduling still needs idempotent job handlers, because a worker can finish after a lease expires. that would make the drop in claim safer for real workloads.

Collapse
 
awaismehr profile image
Muhammad Awais

This is a great list, thank you especially the point about exactly-once scheduling. You're right that a lease expiring mid-job and the worker finishing anyway is a real failure mode, and "wire-compatible with Sidekiq" doesn't change that the handler still has to be idempotent. That's true of Sidekiq itself too, but it's worth saying explicitly rather than letting "drop-in" imply more safety than it delivers.