Resque: queue lists, polling workers, and JSON payloads
Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later.
At a glance
- What is it?
- Resque turns any Ruby class that responds to perform into a Redis backed job. What you get is ordering by queue name, a polling rake task with no job ceiling, and a separate Sinatra app for watching workers. Where it stops is as informative as where it works.
- Who is it for?
- Resque fits a Rails or plain Ruby app that already runs Redis and is happy with queue level ordering plus a separate monitoring app. It does not fit teams that need numeric priorities, a bound on jobs per worker, or Ruby below 3.2.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- resque/resque9,467 ★ · -6
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| resque/resque | 9.5k | 9.5k |
-6 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A queue list, not a number, decides what runs first
Resque has no numeric priority. Ordering comes from the sequence of queue names handed to a worker, which the project calls the queue list:
$ QUEUES=critical,archive,high,low rake resque:workA worker checks the first name until it finds nothing, processes what it takes, and only then moves to the next name, returning to the head of the list after every job it takes from a later one.
Two things it cannot do follow from that. It cannot rank a job above another job, so two jobs both sitting on critical are taken in arrival order with no way to move one ahead. And a queue named last in the list waits longest: continuous traffic on the first name keeps the later ones from being reached at all, so appending bulk work to a list only helps if the head of the list goes idle regularly. The project's own layout leans on that shape, running a general list on one class of machine and pulling archive out onto a machine of its own with a single queue command.
A payload is JSON, so arguments have to be rebuildable
A job is a class name, an argument list, and one perform call. Queues store jobs as simple JSON packages, and enqueuing passes the class plus arguments:
class Repository
def async_create_archive(branch)
Resque.enqueue(Archive, self.id, branch)
end
endThe queue is set by a class instance variable:
class Archive
@queue = :file_serve
def self.perform(repo_id, branch = 'master')
repo = Repository.find(repo_id)
repo.create_archive(branch)
end
endA worker pulls the package back and dispatches it in two lines:
klass, args = Resque.reserve(:file_serve)
klass.perform(*args) if klass.respond_to? :performThat dispatch shape sets the limits. The argument list has to survive a JSON round trip, which is why the example hands over repo_id and a branch string and re-finds the record inside the worker instead of passing a loaded object. And the worker has to be able to load the class at all, which is what the opt-in require of your app in the Rakefile exists for.
The worker loop never finishes on its own
Workers are rake tasks meant to run until something stops them, and the loop the project prints is short:
start
loop do
if job = reserve
job.process
else
sleep 5 # Polling frequency = 5
end
end
shutdownThree consequences matter when you size a deployment. An idle worker does not block on a pop; it sleeps five seconds and asks again, so every dormant worker keeps generating Redis traffic on that cadence, and a fleet of workers multiplies the polls. The loop as printed carries no exit condition, no maximum job count and no time limit, so a worker stays resident for as long as its process lives. The list of worker properties also says workers are resilient to memory bloat and leaks. Shutdown is left to the operator, and for several workers the guidance is blunt:
$ COUNT=2 QUEUE=* rake resque:workersEach of those runs in its own process, and the README says hitting ctrl-c should be sufficient to stop them all.
A splat is alphabetical, and negation cannot express an order
A splat tells a worker to take everything, including queues created on the fly after startup:
$ QUEUE=* rake resque:workThe catch sits in the next line of the documentation: queues are processed in alphabetical order. A splat only worker has ordering, but it is ordering by name rather than by importance, and it is decided at the moment names are compared, so a queue added to your application later lands wherever the alphabet puts it. Named queues can be floated above the splat:
# QUEUE=critical,* rake resque:workNegation subtracts from the splat, by exact name or by prefix:
$ QUEUE=*,!low rake resque:work$ QUEUE=*,!file_* rake resque:workWhat the negation form cannot do is express an order. The documentation states that the order in which negated queues are listed does not matter, so QUEUE=*,!file_* and QUEUE=!file_*,* behave the same. A worker that must handle the archive queue alone therefore needs its own command, and every distinct set of queues means another start line to keep track of across every machine.
Version floors strand older Ruby and Rails stacks on the 2.x line
The install documentation sets high floors. Resque requires Ruby 3.2.0 or newer, lists 3.2, 3.3, 3.4 and 4.0 as supported, and pairs that with Redis server 4.0+, redis gem 4.0+, Rack 2.x or 3.x, and Rails 7.2+ for the ActiveJob integration. The 3.0 notes repeat the shape: Ruby 3.0+ with Ruby 2.x dropped, redis gem 4.0+ tested against 4.x and 5.x, Sinatra 2.0+ with either Rack line, and continued Rails 7.2 and ActiveJob compatibility. Releases shipped recently are 3.2.0 on 2026-10-16, 3.1.0 on 2026-09-16 and 3.0.3 on 2026-09-10, so the 3.x line is where fixes land.
What that rules out is specific. An app on Ruby 3.1, or on a Rails release older than 7.2, falls outside the current support list. A Redis server below 4.0 sits outside the stated range. The single sentence offered for older stacks is that if you need Ruby 2.x support, use Resque 2.x.
Rails workers boot into different configuration than the web app
Under Rails the worker process is configured separately, through the resque:setup task. Three requires in the Rakefile set that up:
require 'resque'
require 'resque/tasks'
require 'your/app' # Include this line if you want your workers to have access to your applicationThe third line decides whether your job classes exist inside the worker, and its own comment marks it optional. Rather than editing the shipped task, Rails apps override it:
task "resque:setup" => :environment do
Grit::Git.git_timeout = 10.minutes
endThe remark that follows explains the intent: the web app should not carry a ten minute git timeout, but in the Resque workers it is fine. That split is the mechanism and the hazard at once. A worker boots into different configuration from the process that enqueued the job, so model loading, credentials, timeouts and anything else a job depends on has to be established inside the setup task or the require list. Configuration the web process applies at runtime is not inherited, and a job that relies on it fails on the worker side while the request that enqueued it reported success.
Monitoring is a standalone Sinatra app, and supervision is left to you
Resque is three parts: a Ruby library for creating, querying and processing jobs, a rake task that starts a worker, and a Sinatra app for monitoring queues, jobs and workers. The front end reports what workers are doing, what workers are not doing, which queues exist, what is in them, general usage stats, and failures. The repository root carries a config.ru for that Rack app, next to bin/, log/ and a docs/ directory.
Every number it shows is read from the same Redis the workers reserve from, and the only condition named for a worker is network access to the Redis server, with workers able to run anywhere holding that. Queues are persistent and provide visibility into their contents, so a backlog shows up as a growing list rather than as an error, and a worker that never registered shows up as absence rather than as a failure.
For process supervision, the repository ships example directories for god and monit alongside examples/async_helper.rb, examples/instance.rb, examples/resque_config.rb and examples/simple.rb.
Editorial conclusion
Resque fits a Rails or plain Ruby app that already runs Redis and is happy with queue level ordering plus a separate monitoring app. It does not fit teams that need numeric priorities, a bound on jobs per worker, or Ruby below 3.2. Before adopting, check the Ruby, Redis server, redis gem, Rack and Rails versions your app already pins, then read every worker start command for the queue list it hardcodes.
Frequently asked questions
What is a resque?
A Redis-backed library for creating background jobs, placing them on multiple queues, and processing them later. It is pronounced like the word rescue, and it ships as three parts: the library, a Rake task for starting a worker, and a Sinatra app for monitoring.
Is it rescue or resque?
The name is Resque, spelled with a que, and the project states it is pronounced like rescue. The homepage is http://resque.github.io/ and the source lives at resque/resque under the MIT license.
What is a resque worker?
A Rake task that runs forever: it starts, reserves a job, processes it, and when it finds none sleeps 5 before polling again. One worker is started with QUEUE=file_serve rake resque:work, and several at once with COUNT=2 QUEUE=* rake resque:workers, each in its own process.
resque vs sidekiq
The project's own documentation does not compare Resque with Sidekiq. What it does fix is that Resque has no numeric priorities, uses the order of the queue list instead, stores jobs as simple JSON packages, and was heavily inspired by DelayedJob.
resque alternative
The one predecessor named is DelayedJob, which the project says Resque was heavily inspired by. Beyond that the documentation does not list replacement libraries, and points instead at its own three parts, including the Sinatra app for monitoring queues, jobs and workers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/resque-resque)Star history chart for your README
[](https://hysenlabs.com/projects/resque-resque)Was this useful?