# sidekiq-cron: scheduled Sidekiq jobs with cron and natural language

> sidekiq-cron is a Ruby scheduling add-on for Sidekiq that enqueues jobs according to cron notation or Fugit natural-language schedules. It is designed for applications that need recurring or delayed work inside a Sidekiq process, with Redis-backed job definitions and a polling thread for schedule discovery.

**sidekiq-cron/sidekiq-cron** — Scheduler / Cron for Sidekiq jobs

- Repository: https://github.com/sidekiq-cron/sidekiq-cron
- Stars: 1,945 · Forks: 304
- Language: Ruby
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/sidekiq-cron-sidekiq-cron

## What sidekiq-cron schedules

sidekiq-cron solves a specific gap in a Sidekiq application: recurring work needs a time definition and a mechanism that enqueues the corresponding Sidekiq job. Without that layer, an application must arrange every periodic execution elsewhere. This project adds that scheduling layer for Ruby, Rails, and non-Rails Sidekiq users.

The scheduled unit requires a unique `name`, a `cron` expression, and a `class`. The expression can use standard five-field cron notation, such as `1 * * * *`, or a natural-language form understood by Fugit, such as `every day at five`. The job definition can also specify a queue, retry policy, arguments, a namespace, an Active Job route, an execution-time argument, a description, and an enabled or disabled status.

The project is aimed at applications that already rely on Sidekiq for background processing. It does not replace a worker implementation. The documented job class receives the arguments supplied by the schedule, and Active Job can be selected with `active_job => true`. The schedule is therefore about dispatch timing, while Sidekiq remains responsible for processing the enqueued work.

## The Sidekiq scheduling thread and Redis model

According to the README, sidekiq-cron runs a thread alongside Sidekiq workers. The thread checks for new jobs to schedule every 30 seconds by default. When several Sidekiq processes or nodes are running, the project states that the same job is not scheduled multiple times, which indicates that schedule discovery includes coordination through the shared Sidekiq environment rather than relying on one operator.

The scheduling data is represented as job properties with values such as `name`, `cron`, `class`, `queue`, `args`, and `status`. These values can originate from a schedule file or from dynamic definitions, because the README lists `source` values for `schedule` and `dynamic`. A schedule file can be changed through `config.cron_schedule_file`, whose default is `config/schedule.yml`. Setting it to `nil` disables automatic loading.

The important operational boundary is that scheduling occurs only when at least one Sidekiq process is running. Running multiple processes is documented as safe for avoiding duplicate scheduling, but it does not remove the runtime requirement. If the Sidekiq processes are stopped, the scheduling thread has no opportunity to discover and enqueue future jobs.

The project also maintains execution history through `cron_history_size`, which defaults to 10. The README exposes this as configuration, but does not describe the exact history schema or retention behavior beyond that setting.

## Installing sidekiq-cron in Ruby and Rails

The documented installation is the standard Ruby gem installation, or a Gemfile entry followed by Bundler. In a Rails application, the configuration belongs in an initializer such as `config/initializers/sidekiq-cron.rb`. Outside Rails, the README requires `require 'sidekiq-cron'` somewhere after `require 'sidekiq'`.

For a Bundler-based application, add the gem and install dependencies with this command:

```bash
bundle install
```

The Gemfile entry is:

```ruby
gem "sidekiq-cron"
```

For a direct installation, the documented command is:

```bash
gem install sidekiq-cron
```

The default configuration enables the add-on, polls every 30 seconds, loads `config/schedule.yml`, keeps 10 history entries, uses `default` as the default namespace, parses natural-language cron strings in `:single` mode, and uses a 60-second reschedule grace period. A Rails initializer can change those settings, for example:

```ruby
Sidekiq::Cron.configure do |config|
  config.cron_schedule_file = 'config/my_schedule.yml'
  config.cron_poll_interval = 10
  config.default_namespace = 'statistics'
end
```

The README does not document a separate sidekiq-cron startup command. The add-on is loaded with Sidekiq, so the application must start its normal Sidekiq process after configuration is in place.

## Defining a first scheduled job

A first job definition needs an identity, a schedule, and the Ruby class that Sidekiq should enqueue. The README gives the following required and optional properties. The `cron` value here runs at one minute past every hour.

```ruby
{
  'name' => 'name_of_job',
  'cron' => '1 * * * *',
  'class' => 'MyClass',
  'queue' => 'name of queue',
  'retry' => '5',
  'args' => '[Array or Hash] of arguments which will be passed to perform method',
  'description' => 'A sentence describing what work this job performs'
}
```

The `name` must be unique. The `class` value is passed to Sidekiq when the schedule becomes due. If the worker needs an execution timestamp, set `date_as_argument => true`; the README says this adds the execution time as the final argument to the `perform` method. For an Active Job application, set `active_job => true`, then use the documented Active Job options such as `queue_name_prefix` and `queue_name_delimiter`.

The README documents automatic loading of `config/schedule.yml`. The exact YAML structure and the Ruby API call for creating a dynamic job should be checked in the current schedule-file documentation before treating the snippet as a complete first-use procedure.

A basic schedule definition can be disabled without deleting it by setting `status` to `disabled`. The README warns that a job's status is not changed in Redis when a job is reloaded unless `status` is explicitly supplied. That behavior matters for operational changes, because an old Redis status can survive a configuration reload.

## Cron parsing, time zones, and polling limits

sidekiq-cron uses Fugit to parse cron lines. With Rails, the expression is evaluated against the timezone configured in Rails. Outside Rails, the default is UTC. A timezone can also be included in the cron line, and the README gives `0 22 * * 1-5 America/Chicago` as the format for that case.

Natural-language schedules have two parsing modes. The default, `:single`, takes the first cron line produced by a phrase and ignores additional lines. Thus, `every day at 3:15 and 4:30` is treated as `15 3 * * *`. With `:strict`, a phrase that would produce multiple cron lines is rejected, so the same text would make the associated job invalid. The mode is configured through `natural_cron_parsing_mode`.

Second precision is available through a six-field expression, `Seconds Minutes Hours Days Months DayOfWeek`. For example, `*/30 * * * * *` schedules a job every 30 seconds, but the polling interval defaults to 30 seconds. The README explicitly warns that the polling interval may need to be lower than the job interval for sub-minute jobs. A poll interval of 10 seconds can be configured:

```ruby
Sidekiq::Cron.configure do |config|
  config.cron_poll_interval = 10
end
```

This means the schedule expression and dispatch check are separate concerns. Setting a 10-second cron expression does not by itself guarantee a check every 10 seconds.

## Namespaces, reloads, and operational limits

Namespaces group scheduled jobs. A job without a namespace uses `default`, which can be changed with `default_namespace`. The set of namespaces an application uses can be restricted with `available_namespaces`. This is useful when schedules are separated by business area, but the README does not provide a full API for creating and managing every namespace operation.

There is a concrete migration hazard. If an existing job is moved to a differently named namespace, the gem does not automatically delete the cron job associated with the old namespace. Both old and new records can then be active. The documented cleanup uses `Sidekiq::Cron::Job.all` and `destroy`:

```ruby
Sidekiq::Cron::Job.all('YOUR_OLD_NAMESPACE_NAME').each { |job| job.destroy }
```

This is not a cosmetic detail. A namespace rename can create duplicate schedules, so the old records need to be removed before the renamed schedule is relied upon. The same caution applies to status changes during reloads, because status is preserved in Redis unless explicitly included.

The add-on is not a general-purpose scheduler outside Sidekiq. It schedules only while a Sidekiq process exists, checks at a configurable interval, and is designed for Ruby job classes and Sidekiq queues. Applications that require independent scheduling infrastructure, different queue systems, or process-independent guarantees would need a different design.

## Maintenance, upgrades, and the scheduling alternative

The repository is not archived, and its last push was on 2026-10-16. Recent releases listed in the repository include v2.4.0 on 2026-05-06, v2.3.1 on 2025-08-08, and v2.3.0 on 2025-05-12. The README tells users to read `CHANGELOG.md` before upgrading. The repository is licensed under MIT, so the license file and its terms govern redistribution and use.

The main upgrade-specific behavior documented here is operational rather than binary compatibility. Schedule files can be reloaded, but Redis status is preserved unless `status` is explicitly set. Namespace changes can leave old records behind. Sub-minute schedules may need a lower poll interval. These are configuration points that should be checked against `CHANGELOG.md` during an upgrade.

A different approach is an external scheduler that periodically invokes Sidekiq's job enqueue API. Its scheduling lifecycle would be outside the Sidekiq worker process, rather than in the scheduling thread described by sidekiq-cron. The trade-off is architectural: sidekiq-cron keeps cron definitions and Sidekiq dispatch together and documents duplicate avoidance across Sidekiq processes, while an external scheduler separates those responsibilities. The available documentation does not specify the exact commands or APIs required for that alternative, so it should not be treated as a drop-in replacement.

## Conclusion

Adopt sidekiq-cron when a Sidekiq application needs recurring job definitions that can be loaded from configuration or managed through the library. Do not choose it for sub-minute work without lowering `cron_poll_interval`, or for separate namespace migrations without deleting old records first. Verify Sidekiq and Ruby compatibility, the intended timezone, Redis contents, and the exact schedule before relying on it in production.

## FAQ

### How do I install sidekiq-cron in a Ruby application?

Run `gem install sidekiq-cron`, or add `gem "sidekiq-cron"` to the Gemfile and run `bundle install`. Outside Rails, require `sidekiq-cron` after requiring `sidekiq`.

### How does sidekiq-cron prevent the same job from running in multiple Sidekiq processes?

The README states that sidekiq-cron checks for new jobs every 30 seconds and does not schedule the same job multiple times when multiple Sidekiq processes or nodes are running. The README does not describe the lower-level Redis coordination implementation.

### Can sidekiq-cron run jobs every 30 seconds?

Yes, it supports second-precision six-field cron expressions, and the README gives `*/30 * * * * *` as an example. Because the default polling interval is 30 seconds, the README says you may need to lower `cron_poll_interval`, for example to 10.

## Sources

- [Issues](https://github.com/sidekiq-cron/sidekiq-cron/issues)
- [License: MIT](https://github.com/sidekiq-cron/sidekiq-cron/blob/master/LICENSE)
- [README](https://github.com/sidekiq-cron/sidekiq-cron/blob/master/README.md)
- [Releases](https://github.com/sidekiq-cron/sidekiq-cron/releases)
- [sidekiq-cron/sidekiq-cron on GitHub](https://github.com/sidekiq-cron/sidekiq-cron)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sidekiq-cron-sidekiq-cron
