How to Configure Scheduled Maintenance Jobs with Sidekiq-Cron in Maybe Finance

Maybe Finance configures scheduled maintenance jobs using the sidekiq-cron gem by defining cron expressions in config/schedule.yml, routing jobs through a dedicated scheduled queue configured in config/sidekiq.yml, and initializing the system with a 10-minute catch-up window in config/initializers/sidekiq.rb.

The open-source personal finance application Maybe Finance relies on periodic background tasks to synchronize market data, clean up stale records, and perform other maintenance operations. Understanding how these scheduled maintenance jobs are configured with Sidekiq-Cron provides insight into the robust, declarative background processing architecture that keeps the application data fresh and accurate.

Understanding the Sidekiq-Cron Architecture

Maybe implements scheduled jobs through three coordinated configuration layers. The architecture separates schedule definitions from queue routing and runtime initialization, allowing for clear, maintainable cron management.

The three core components are:

Step 1: Defining Cron Schedules in schedule.yml

The config/schedule.yml file serves as the central registry for all recurring maintenance tasks. Each entry maps a unique job name to a Sidekiq worker class, cron schedule, and target queue.

Structure of the Cron Definition File

Entries follow a YAML structure specifying the cron expression, class name, and queue assignment:


# config/schedule.yml

daily_market_sync:
  cron: "0 22 * * 1-5"   # 5 PM EST / 6 PM EDT, Monday through Friday

  class: "MarketDataSyncWorker"
  queue: scheduled

stale_sync_cleanup:
  cron: "0 * * * *"      # Every hour on the hour

  class: "StaleSyncCleanerWorker"
  queue: scheduled

The cron field accepts standard cron syntax, while the class field references the worker implementation located in app/workers/ (for example, app/workers/market_data_sync_worker.rb).

Step 2: Configuring the Scheduled Queue in sidekiq.yml

Maybe routes all cron-triggered jobs through a dedicated queue to separate scheduled maintenance from user-triggered background tasks. This isolation prevents maintenance workloads from blocking critical user-facing jobs.

Queue Weight and Priority

The config/sidekiq.yml file declares the scheduled queue with a weight of 10, giving it moderate priority relative to other queues:


# config/sidekiq.yml

:queues:
  - [default, 5]
  - [mailers, 1]
  - [scheduled, 10]

The weight value determines how often Sidekiq checks this queue for work relative to others. A weight of 10 ensures timely execution of maintenance tasks without starving the default queue.

Step 3: Initializing Sidekiq-Cron in the Rails Initializer

The runtime configuration lives in config/initializers/sidekiq.rb, where Maybe boots the sidekiq-cron system and defines how it handles schedule loading and job catch-up behavior.

Loading the Schedule File

The initializer invokes Sidekiq::Cron.configure to load the YAML schedule and apply global settings:


# config/initializers/sidekiq.rb

Sidekiq::Cron.configure do |config|
  # Load the schedule file

  config.load_from_yaml("#{Rails.root}/config/schedule.yml")
  
  # 10-minute catch-up window (see comment on line 14)

  config.catch_up_window = 10.minutes
end

Configuring the Catch-Up Window

The catch_up_window parameter set to 10.minutes provides a grace period for missed executions. If a cron tick occurs while the Sidekiq process is restarting or deploying, the job will still be enqueued when the new process starts, provided the downtime does not exceed ten minutes.

How Scheduled Maintenance Jobs Execute

When the Rails process starts, the initializer runs Sidekiq::Cron.configure, which performs the following sequence:

  1. Parses config/schedule.yml and creates a Sidekiq::Cron::Job instance for each entry
  2. Maps each cron job to its specified Sidekiq worker class (e.g., MarketDataSyncWorker)
  3. Enqueues jobs to the scheduled queue defined in config/sidekiq.yml when the cron expression triggers
  4. Applies the 10-minute catch-up logic to ensure jobs are not lost during deployments

The worker classes themselves reside in app/workers/ and implement the actual maintenance logic, such as syncing market data or cleaning stale records.

Summary

Maybe Finance configures scheduled maintenance jobs with Sidekiq-Cron through a three-layer declarative setup:

  • Schedule definitions live in config/schedule.yml, mapping cron expressions to worker classes
  • Queue routing is handled in config/sidekiq.yml via a dedicated scheduled queue with weight 10
  • Runtime initialization occurs in config/initializers/sidekiq.rb, loading the schedule and configuring a 10-minute catch-up window to prevent missed jobs during deployments

This architecture separates scheduling logic from execution logic, ensuring reliable, maintainable background processing for critical financial data synchronization.

Frequently Asked Questions

What is the purpose of the catch-up window in Sidekiq-Cron?

The catch-up window ensures that scheduled jobs are not lost during application deployments or process restarts. Maybe Finance sets this to 10 minutes in config/initializers/sidekiq.rb, meaning if a cron tick occurs while Sidekiq is temporarily offline, the job will still be enqueued when the process restarts, provided the downtime does not exceed the configured window.

How do you add a new scheduled maintenance job to Maybe Finance?

To add a new job, first create a Sidekiq worker class in app/workers/ (for example, app/workers/new_maintenance_worker.rb). Then add an entry to config/schedule.yml specifying the cron expression, the class name, and the queue (typically scheduled). Finally, restart the Sidekiq process to load the new schedule via the initializer in config/initializers/sidekiq.rb.

What happens if a scheduled job fails in Sidekiq-Cron?

When a scheduled job fails, Sidekiq's standard retry mechanism applies according to the worker class configuration. The job remains in the scheduled queue (or moves to the retry queue) and Sidekiq attempts to reprocess it based on the retry count and backoff strategy defined in the worker. The cron schedule continues to enqueue new instances independently of previous failures.

Where are the worker classes for scheduled jobs defined in Maybe Finance?

Worker classes reside in the app/workers/ directory. For example, the MarketDataSyncWorker referenced in config/schedule.yml is defined in app/workers/market_data_sync_worker.rb. These classes inherit from Sidekiq's worker base class and implement the perform method containing the actual maintenance logic executed on schedule.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →