Open-source project
resque/resque-scheduler avatar
resque/resque-scheduler

resque-scheduler: Future and Recurring Jobs for Resque

A light-weight job scheduling system built on top of Resque

1,746 stars479 forksRubyMIT

At a glance

What is it?
resque-scheduler adds recurring schedules and one-time delayed jobs to a Resque application. It suits Ruby teams that already depend on Resque and need a separate, long-running scheduler process.
Who is it for?
Adopt resque-scheduler when the application already uses Resque and needs cron-like schedules, delayed enqueueing, or Active Job support through the Resque adapter. Do not choose it if precise execution times, distributed process management, or non-Resque queues are primary requirements.
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 3 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 October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The Scheduling Gap Resque Leaves Open

Resque handles work placed on queues for workers to consume, but resque-scheduler adds a time dimension. It is intended for Ruby applications that already rely on Resque and need to place a job into a work queue at a later point or run it repeatedly. The README describes two distinct models. A scheduled job is comparable to a cron entry: it becomes eligible for queueing each time its configured interval elapses. A delayed job is a one-time Resque job associated with a future timestamp.

That distinction matters when choosing an API. `Resque.enqueue_in` expresses a relative delay, while `Resque.enqueue_at` accepts an absolute time. The same model applies to recurring schedules loaded from YAML. This makes resque-scheduler suitable for follow-up email, maintenance work, and other jobs whose eligibility depends on time rather than immediate worker availability.

It is not presented as a general-purpose distributed scheduler. The process polls delayed work and manages recurring entries, but the README does not describe calendar triggers, cron expression parsing, execution guarantees, failover, or a built-in service-management system. Its clearest boundary is the existing Resque architecture. Teams looking for those broader scheduling capabilities need to assess the missing behavior rather than assume that the word scheduler covers it.

Delayed Queue-to-Worker Data Flow

The central operational path has two stages. First, calling `Resque.enqueue_in` stores a serialized job in Resque's delayed queue for the requested delay. The scheduler process later polls that delayed queue. Once the eligible time has passed, it transfers the item into the normal Resque work queue for the job. A Resque worker can then process it when capacity becomes available.

The README is explicit that the requested time is not an exact execution deadline. The job does not necessarily fire at that instant. It moves to the work queue after the time has passed, and its completion still depends on worker availability. The scheduler interval is therefore relevant to handoff latency. The documented `RESQUE_SCHEDULER_INTERVAL` environment variable sets the checking interval in seconds and defaults to `5`, with the value passed through `Kernel#Float()`.

Queue selection can remain explicit. `Resque.enqueue_at_with_queue` accepts a queue name, timestamp, job class, and arguments. Active Job subclasses can also use the delayed APIs when Active Job is configured with the `:resque` adapter. The README says those jobs are handed to `perform_later`, using `set(wait_until:)` for delayed work, and that `queue_as` applies unless a queue is supplied.

This design keeps normal worker processing familiar, but it also creates two capacity boundaries. Delayed work can wait in the delayed queue, then wait again in a work queue. Monitoring must account for both locations if that becomes relevant to the application's operations.

Installing the Gem and Defining a Recurring Schedule

The README lists direct gem installation and Gemfile configuration. For a Bundler-managed application, declare the dependency in the Gemfile rather than relying on the global gem command.

ruby
gem 'resque-scheduler'

The scheduler needs configuration through the `resque:setup` task because resque-scheduler expects the same Resque connection details as Resque. The documented integration also requires the scheduler tasks, assigns the Redis endpoint, loads the schedule YAML, and defines `resque:scheduler` as depending on `setup_schedule`.

ruby
require 'resque/tasks'
require 'resque/scheduler/tasks'

namespace :resque do
  task :setup do
    require 'resque'
    Resque.redis = 'localhost:6379'
  end

  task :setup_schedule => :setup do
    require 'resque-scheduler'
    Resque.schedule = YAML.load_file('your_resque_schedule.yml')
  end

  task :scheduler => :setup_schedule
end

Replace `your_resque_schedule.yml` with the application's schedule file. The README says the schedule may be any hash and that YAML is usually the easiest representation. A job entry can contain a `queue`; when it does, the scheduler does not need to require the corresponding job class. Without that information, the integration can require the job definitions, as shown in the README with `require 'jobs'`.

Start the process with the documented Rake command:

bash
rake resque:scheduler

In Rails or another environment with an environment-loading task, the documented form is:

bash
rake environment resque:scheduler

The command does not return after normal scheduling work. The scheduler process remains alive because it must continue queueing recurring entries and polling delayed jobs. Rails applications also receive the `resque:scheduler` task and Resque web UI tabs through the Railtie, according to the README.

Running the Standalone Scheduler Process

A separate executable is available after the gem is installed. This is useful when the scheduler should not be launched through the application's Rake environment. The only discovery command documented in the README is the help option:

bash
resque-scheduler --help

The executable and Rake task accept the same environment variables. `INITIALIZER_PATH` can load a Ruby file before `resque` and `resque/scheduler` are required, which gives the process application-specific setup. `LOGFILE` defaults to `$stdout`, while `LOGFORMAT` accepts `text`, `json`, or `logfmt`. `PIDFILE` can record the process PID, and `BACKGROUND` can invoke `Process.daemon` where supported.

For recurring schedules that need to change while the process runs, the README documents `Resque::Scheduler.dynamic = true`. The scheduler then checks for schedule changes and applies them on the fly. The configuration can also use the `DYNAMIC_SCHEDULE` environment variable. The project states that this feature is available in version 2.0.0 or later.

The README does not document clustering scheduler processes, leader election, automatic restart, health checks, or graceful deployment. Calling this process long-running identifies the deployment requirement, but it does not solve it. The application owner must determine how the scheduler fits into its service manager or platform. That absence is especially relevant because normal Resque workers and the scheduler perform different jobs.

Resque Worker Compatibility and Active Job Constraints

resque-scheduler adds scheduling without replacing Resque workers. Delayed jobs ultimately become ordinary work-queue items, so worker availability still determines when they complete. For applications using `resque-pool`, the README specifies an after-prefork hook that reconnects Redis:

ruby
task 'resque:pool:setup' do
  Resque::Pool.after_prefork do |job|
    Resque.redis.reconnect
  end
end

This integration addresses Redis connection state after a process forks. It is a concrete requirement rather than a general performance optimization.

Active Job support also comes with an adapter constraint. The base class must use the `:resque` adapter. Because resque-scheduler hands Active Job work to `perform_later`, jobs are stored through the adapter's `JobWrapper`. The README notes a practical consequence: the helper methods `delayed?`, `remove_delayed`, and `find_delayed_selection` do not match Active Job class names, since the stored class is the wrapper rather than the original Active Job subclass.

This limitation affects inspection and management code. If an application needs to find or remove delayed Active Job entries by their original class, the documented helpers are not sufficient as written. The README also does not describe direct support for scheduling Active Job classes loaded under a different queue configuration beyond the stated `queue_as` behavior. Such an application should test its exact job class, adapter, and management path before relying on delayed operations.

MIT Licensing and Version Upgrade Considerations

The repository is licensed under MIT. That permits use, modification, distribution, and private incorporation under the license's conditions, but this review does not interpret those legal terms or assess an application's compliance needs.

The release record provides several concrete upgrade checkpoints. Version 5.0.0 was released on 2026-01-15, followed by v5.0.1 on 2026-10-11. Version 4.11.0 was released on 2024-12-30. The last push was on 2026-10-13, and the repository is not archived. These facts show recent development activity, but they do not describe migration effort.

Moving from v4 to v5 is a major-version change and should not be treated as a routine gem update without reviewing `CHANGELOG.md` and the project test suite for the application. The README does not provide a v4-to-v5 migration guide, supported dependency ranges, or a list of breaking changes. It also does not establish compatibility with every supported Ruby, Rails, Resque, or `resque-pool` version.

Operational upgrade cost is likely to involve more than editing the Gemfile. Existing schedule YAML, Rake tasks, Redis connectivity, worker hooks, initializer loading, logging, and any code that queries delayed job classes need to remain aligned with the selected release. The separate scheduler process also needs a deployment plan that avoids unintentionally running incompatible versions alongside workers.

Where Resque-Scheduler Differs from a Full Job Platform

A real alternative is a hosted or self-managed job platform that provides scheduling, delayed execution, worker capacity, operational monitoring, and retry handling as one managed service. Its approach differs at the infrastructure boundary: the application submits work through a dedicated platform, while that service owns scheduling infrastructure and worker operations. resque-scheduler leaves the application responsible for Resque, Redis, workers, and the always-running scheduler process.

Another alternative is maintaining a separate scheduled process that writes ready jobs directly into Resque. That can work when the application already has reliable deployment, locking, and observability for its scheduler. resque-scheduler reduces the amount of custom polling and delayed-queue code by operating directly on Resque queues and exposing recurring and delayed APIs.

The trade-off is control tied to Resque conventions. The benefit is close integration with existing queues, classes, and `resque-pool`. The cost is that timing precision, process supervision, clustering, and service-level monitoring are not described as built-in scheduler features. A team already standardized on a managed scheduling service may gain more operational capability by staying with that platform. A team with a simple Resque deployment and direct operational ownership gets a smaller Ruby-native mechanism for future and recurring work.

Editorial conclusion

Adopt resque-scheduler when the application already uses Resque and needs cron-like schedules, delayed enqueueing, or Active Job support through the Resque adapter. Do not choose it if precise execution times, distributed process management, or non-Resque queues are primary requirements. Before adoption, verify worker deployment, Redis access, schedule loading, and the operational ownership of the separate scheduler process.

Frequently asked questions

How do I install resque-scheduler in a Ruby application?

The README documents `gem install resque-scheduler` for a direct installation and `gem 'resque-scheduler'` for a Gemfile-based application. It must also be connected to Resque through the `resque:setup` task.

Does resque-scheduler execute a delayed job at the exact requested time?

No. After the requested time passes, the scheduler moves the job from the delayed queue into the normal Resque work queue. A worker must then be available to process it.

Can resque-scheduler schedule Active Job classes?

Yes, provided Active Job uses the `:resque` adapter. The job is handed to `perform_later`, and its `queue_as` applies unless another queue is supplied.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. resque/resque-scheduler on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/resque-resque-scheduler.svg)](https://hysenlabs.com/projects/resque-resque-scheduler)

Was this useful?