---
title: "Crons"
description: "Sentry Crons allows you to monitor the uptime and performance of any scheduled, recurring job in your application."
url: https://docs.sentry.io/platforms/ruby/guides/rack/crons/
---

# Set Up Crons | Sentry for Rack Middleware

Once implemented, it'll allow you to get alerts and metrics to help you solve errors, detect timeouts, and prevent disruptions to your service.

## [Requirements](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#requirements)

* Use our [getting started](https://docs.sentry.io/platforms/ruby/guides/rack.md) guide to install and configure the Sentry Ruby SDK (min v5.12.0) for your recurring job.
* [Create and configure](https://sentry.io/issues/alerts/new/crons/) your first Monitor.

## [Job Monitoring](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#job-monitoring)

If you're using `sidekiq-cron` or `sidekiq-scheduler`, Sentry can automatically capture check-ins for all jobs that are scheduled to run periodically. To achieve this, you need to enable the corresponding Sentry plugin:

```rb
Sentry.init do |config|
  config.enabled_patches += [:sidekiq_cron]
  # or, for sidekiq-scheduler:
  config.enabled_patches += [:sidekiq_scheduler]
end
```

More generally, popular job frameworks such as `ActiveJob` and `Sidekiq` with a `perform` method can use the `Sentry::Cron::MonitorCheckIns` mixin module to automatically capture check-ins.

```rb
class ExampleJob < ApplicationJob
  include Sentry::Cron::MonitorCheckIns

  sentry_monitor_check_ins

  def perform(*args)
    # do stuff
  end
end
```

You can pass in optional attributes to `sentry_monitor_check_ins` as follows.

```rb
# slug defaults to the job class name
sentry_monitor_check_ins slug: 'custom_slug'

# define the monitor config with an interval
# the units supported are :year, :month, :week, :day, :hour, :minute
sentry_monitor_check_ins monitor_config: Sentry::Cron::MonitorConfig.from_interval(1, :minute)

# define the monitor config with a crontab
sentry_monitor_check_ins monitor_config: Sentry::Cron::MonitorConfig.from_crontab('5 * * * *')
```

## [Manual Setup](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#manual-setup)

If you're using `Clockwork` or `Whenever`, you'll need to instrument your jobs manually.

### [Check-Ins (Recommended)](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#check-ins-recommended)

Check-in monitoring allows you to track a job's progress by completing two check-ins: one at the start of your job and another at the end of your job. This two-step process allows Sentry to notify you if your job didn't start when expected (missed) or if it exceeded its maximum runtime (failed).

```ruby
check_in_id = Sentry.capture_check_in('<monitor-slug>', :in_progress)
# Execute your scheduled task here...
Sentry.capture_check_in('<monitor-slug>', :ok, check_in_id: check_in_id)
```

If your job execution fails, you can notify Sentry about the failure:

```ruby
Sentry.capture_check_in('<monitor-slug>', :error, check_in_id: check_in_id)
```

### [Heartbeat](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#heartbeat)

Heartbeat monitoring notifies Sentry of a job's status through one check-in. This setup will only notify you if your job didn't start when expected (missed). If you need to track a job to see if it exceeded its maximum runtime (failed), use check-ins instead.

```ruby
Sentry.capture_check_in('<monitor-slug>', :ok)
```

If your job execution fails, you can notify Sentry about the failure:

```ruby
Sentry.capture_check_in('<monitor-slug>', :error)
```

## [Upserting Cron Monitors](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#upserting-cron-monitors)

You can create and update your Monitors programmatically with code rather than [creating and configuring them in Sentry.io](https://sentry.io/issues/alerts/new/crons/).

First create a config object from either a crontab or an interval.

```ruby
# Create a config from a crontab schedule (every 10 minutes)
monitor_config = Sentry::Cron::MonitorConfig.from_crontab(
  '5 * * * *',
  checkin_margin: 5, # Optional check-in margin in minutes
  max_runtime: 15, # Optional max runtime in minutes
  timezone: 'Europe/Vienna', # Optional timezone
)

# Create a config from an interval schedule (every 10 minutes)
monitor_config = Sentry::Cron::MonitorConfig.from_interval(
  10,
  :minute,
  checkin_margin: 5, # Optional check-in margin in minutes
  max_runtime: 15, # Optional max runtime in minutes
  timezone: 'Europe/Vienna', # Optional timezone
)
```

Then, use that config object during your check-ins.

```ruby
# 🟡 Notify Sentry your job is running:
check_in_id = Sentry.capture_check_in(
  '<monitor-slug>',
  :in_progress,
  monitor_config: monitor_config
)

# Execute your scheduled task here...

# 🟢 Notify Sentry your job has completed successfully:
Sentry.capture_check_in(
  '<monitor-slug>',
  :ok,
  check_in_id: check_in_id,
  monitor_config: monitor_config
)`
```

## [Alerts](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#alerts)

When your recurring job fails to check in (missed), runs beyond its configured maximum runtime (failed), or manually reports a failure, Sentry will create an error event with a tag to your monitor.

To receive alerts about these events:

1. Navigate to **Alerts** in the sidebar.
2. Create a new alert and select "Issues" under "Errors" as the alert type.
3. Configure your alert and define a filter match to use: `The event's tags match {key} {match} {value}`.

Example: `The event's tags match monitor.slug equals my-monitor-slug-here`

Learn more in [Issue Alert Configuration](https://docs.sentry.io/product/alerts/create-alerts/issue-alert-config.md).

## [Rate Limits](https://docs.sentry.io/platforms/ruby/guides/rack/crons.md#rate-limits)

To prevent abuse and resource overuse, Crons limits check-ins to **6 per minute for each monitor environment**.

For example, if you have a monitor called "database-backup" with two environments:

* `database-backup` in environment `production` can send up to 6 check-ins per minute
* `database-backup` in environment `staging` can also send up to 6 check-ins per minute
* Combined, they can send up to 12 check-ins per minute

You can verify if any check-ins are being dropped by visiting the [Usage Stats](https://docs.sentry.io/product/stats.md#usage-stats) page. To avoid dropped check-ins, ensure your monitors don't exceed the rate limit.
