Check-Ins
Cron monitoring protocol for reporting job start, success, and failure via check-in envelopes.
Cron check-ins allow Sentry to monitor the health of recurring jobs (cron jobs, scheduled tasks, periodic workers). An SDK sends check-in envelopes to report when a job starts, succeeds, or fails. Sentry uses this data to detect missed, late, and failing executions.
Related specs:
- Envelopes — transport format
A monitor is a named entity in Sentry that tracks a recurring job. Each monitor is identified by a unique monitor_slug. Monitors can be created manually in Sentry or upserted by the SDK alongside check-in data.
A check-in is a single status report for one execution of a monitored job, sent as a check_in envelope item.
Each job execution produces two check-ins that share the same check_in_id:
[job starts] → in_progress → [job ends] → ok / error
in_progress— the job has startedok— the job completed successfullyerror— the job failed
Sentry uses the time between the in_progress and terminal (ok/error) check-ins to compute duration, and the absence of a terminal check-in within max_runtime to detect timeouts.
SDKs can send monitor configuration (schedule, thresholds, timezone) alongside a check-in. Sentry creates the monitor if it doesn't exist or updates it if it does. This eliminates the need for manual monitor setup.
SDKs MUST generate a unique check_in_id (UUID v4) when a job execution starts and send a check-in with status in_progress.
When the job completes, SDKs MUST send a second check-in with the same check_in_id and status ok (success) or error (failure).
SDKs SHOULD compute the duration field for terminal check-ins (ok or error) by measuring the elapsed time since the in_progress check-in was sent.
SDKs SHOULD include a contexts.trace object with a trace_id field to link the check-in to associated errors and traces.
If the job execution is part of an active trace, the SDK SHOULD use that trace's trace_id. Otherwise, the SDK MAY generate a new trace_id for correlation purposes.
SDKs MAY send a check-in with check_in_id set to an empty UUID (128-bit zero value, 00000000000000000000000000000000) to indicate that Sentry SHOULD update the most recent in_progress check-in for the given monitor.
If no in_progress check-in exists, Sentry creates a new one.
This is useful for fire-and-forget patterns where the SDK does not retain the original check_in_id.
SDKs MAY include a monitor_config object in the check-in payload. When present, Sentry creates the monitor if it does not exist, or updates its configuration if it does.
SDKs SHOULD only send monitor_config on the first check-in of a job execution (the in_progress check-in), not on every check-in.
SDKs MAY provide integrations that automatically instrument popular scheduling libraries. When available, these integrations SHOULD:
- Automatically discover scheduled jobs and derive
monitor_slugvalues. - Send
in_progressand terminal check-ins for each job execution. - Upsert monitor configuration based on the library's schedule definition.
Known integrations include Celery Beat (Python), node-cron / cron / node-schedule (JavaScript), Sidekiq-Cron (Ruby), and Oban/Quantum (Elixir).
A check-in is sent as a check_in envelope item containing a JSON object.
{
"check_in_id": "83a7c03ed0a04e1b97e2e3b18d38f244",
"monitor_slug": "my-monitor",
"status": "in_progress",
"duration": 10.0,
"release": "1.0.0",
"environment": "production",
"contexts": {
"trace": {
"trace_id": "8f431b7aa08441bbbd5a0100fd91f9fe"
}
}
}
| Field | Type | Required | Since | Description |
|---|---|---|---|---|
check_in_id | String | REQUIRED | 1.0.0 | Client-generated UUID identifying this job execution. MAY be an empty UUID (all zeros) to update the most recent in_progress check-in (since 1.2.0). |
monitor_slug | String | REQUIRED | 1.0.0 | The distinct slug identifying the monitor. |
status | String | REQUIRED | 1.0.0 | One of in_progress, ok, or error. |
duration | Number | OPTIONAL | 1.0.0 | Duration of the job execution in seconds. Only takes effect for ok or error status. |
release | String | OPTIONAL | 1.0.0 | The release version. |
environment | String | OPTIONAL | 1.0.0 | The environment name. |
monitor_config | Object | OPTIONAL | 1.1.0 | Monitor configuration for upsert. See Monitor Configuration Payload. |
contexts | Object | OPTIONAL | 1.3.0 | Contextual information. Currently supports trace context with trace_id for linking check-ins to errors. |
Envelope constraints:
- A
check_initem MUST occur at most once per envelope. - This item can either be included in an Envelope with other items, or it MAY be sent by itself.
- Maximum item size: 100 KiB.
Envelope Headers: None
Additional Item Headers: None
When included, the monitor_config object supports the following fields:
{
"monitor_config": {
"schedule": {
"type": "crontab",
"value": "0 * * * *"
},
"checkin_margin": 5,
"max_runtime": 30,
"failure_issue_threshold": 2,
"recovery_threshold": 2,
"timezone": "America/Los_Angeles",
"owner": "user:john@example.com"
}
}
| Field | Type | Required | Since | Description |
|---|---|---|---|---|
schedule | Object | REQUIRED | 1.1.0 | Schedule configuration. See Schedule Configuration. |
checkin_margin | Number | OPTIONAL | 1.1.0 | Allowed margin in minutes after the expected check-in time before the monitor is considered missed. |
max_runtime | Number | OPTIONAL | 1.1.0 | Allowed duration in minutes that a monitor may be in_progress before being considered failed due to timeout. |
failure_issue_threshold | Number | OPTIONAL | 1.4.0 | Number of consecutive failed check-ins before an issue is created. |
recovery_threshold | Number | OPTIONAL | 1.4.0 | Number of consecutive OK check-ins before an issue is resolved. |
timezone | String | OPTIONAL | 1.1.0 | A tz database string for the monitor's execution schedule timezone. |
owner | String | OPTIONAL | 1.5.0 | An actor identifier string, e.g. user:john@example.com or team:a-sentry-team. |
This configuration format differs slightly from what is accepted in the monitors frontend APIs.
The schedule object MUST contain a type field set to either crontab or interval.
Crontab schedule:
| Field | Type | Required | Description |
|---|---|---|---|
type | String | REQUIRED | "crontab" |
value | String | REQUIRED | A crontab expression, e.g. "0 * * * *". |
Interval schedule:
| Field | Type | Required | Description |
|---|---|---|---|
type | String | REQUIRED | "interval" |
value | Number | REQUIRED | The interval value. |
unit | String | REQUIRED | One of year, month, week, day, hour, minute. |
SDKs MUST expose a top-level function to send a check-in:
captureCheckIn(checkIn, monitorConfig?) -> checkInId
Parameters:
checkIn— Object containing at minimummonitorSlugandstatus. For terminal check-ins, also includescheckInId(from the initialin_progresscall) and optionallyduration.monitorConfig— OPTIONAL. Monitor configuration for upsert (schedule, margins, thresholds).
Returns: The checkInId (string), so callers can correlate the in_progress and terminal check-ins.
Naming SHOULD follow the SDK's language conventions:
captureCheckIn(JavaScript, Java)capture_check_in(Python, Ruby, Elixir)CaptureCheckIn(Go, .NET)
SDKs SHOULD expose a higher-level wrapper that automatically sends in_progress and ok/error check-ins around a callback:
withMonitor(monitorSlug, callback, monitorConfig?) -> callbackResult
The wrapper MUST:
- Send an
in_progresscheck-in before invoking the callback. - Send an
okcheck-in if the callback completes without error. - Send an
errorcheck-in if the callback throws or returns a failure. - Compute and include
durationin the terminal check-in.
SDKs MAY additionally provide language-idiomatic alternatives:
- Decorators (Python):
@monitor(monitor_slug='slug') - Context managers (Python):
with monitor(monitor_slug='slug'): - Mixins (Ruby):
include Sentry::Cron::MonitorCheckIns - Annotations (Java/Kotlin): framework-specific annotations
Check-in events MUST NOT go through the beforeSend hook. The beforeSend hook is reserved for error events.
SDKs MAY implement a dedicated beforeSendCheckIn hook that applies only to check-in events.
// Start
checkInId = captureCheckIn({
monitorSlug: "data-sync",
status: "in_progress"
})
// ... execute job ...
// Complete
captureCheckIn({
monitorSlug: "data-sync",
checkInId: checkInId,
status: "ok",
duration: 12.5
})
Envelope payload for the first check-in:
{
"check_in_id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"monitor_slug": "data-sync",
"status": "in_progress"
}
Envelope payload for the terminal check-in:
{
"check_in_id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"monitor_slug": "data-sync",
"status": "ok",
"duration": 12.5
}
result = withMonitor("daily-report", () => {
return generateReport()
}, {
schedule: { type: "crontab", value: "0 2 * * *" },
checkinMargin: 10,
maxRuntime: 60,
timezone: "America/New_York"
})
The in_progress envelope payload includes the monitor config:
{
"check_in_id": "f7e8d9c0b1a2f7e8d9c0b1a2f7e8d9c0",
"monitor_slug": "daily-report",
"status": "in_progress",
"monitor_config": {
"schedule": { "type": "crontab", "value": "0 2 * * *" },
"checkin_margin": 10,
"max_runtime": 60,
"timezone": "America/New_York"
}
}
The terminal envelope payload omits the config:
{
"check_in_id": "f7e8d9c0b1a2f7e8d9c0b1a2f7e8d9c0",
"monitor_slug": "daily-report",
"status": "ok",
"duration": 45.3
}
| Version | Date | Summary |
|---|---|---|
1.6.0 | 2025-09-18 | Added hook requirements (beforeSend exclusion, optional beforeSendCheckIn) |
1.5.0 | 2024-04-24 | Added owner field to monitor_config |
1.4.1 | 2023-12-18 | Added failure_issue_threshold and recovery_threshold to monitor_config JSON example |
1.4.0 | 2023-12-13 | Added failure_issue_threshold and recovery_threshold to monitor_config |
1.3.1 | 2023-07-10 | Fixed typo in checkin_margin and max_runtime descriptions |
1.3.0 | 2023-06-26 | Added trace context support for linking check-ins to errors |
1.2.1 | 2023-06-06 | Clarified zero UUID wording to specify "most recent in_progress" check-in |
1.2.0 | 2023-06-05 | Added zero UUID support for updating most recent in_progress check-in |
1.1.0 | 2023-04-18 | Added monitor upsert support with schedule configuration |
1.0.1 | 2023-04-17 | Improved monitor_slug example (UUID replaced with human-readable slug) |
1.0.0 | 2023-03-21 | Initial spec — basic check-in payload |
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").