Scheduler stops. Site stays up.
A deploy clobbers your cron entry. The app responds 200. No one fires the scheduler. Your nightly emails stop.
GET /health 200 ok schedule:run · 17h ago
A background job can exit 0 and still do nothing. Crontinel keeps those as two states. Check in from curl, Node, Python, Sidekiq, or GitHub Actions. The email still goes out when the assistant is off.
The job exited 0. It processed nothing. The run still looks green.
A URL returning 200 does not tell you the job did the work. Crontinel stores the process status and the business result separately. A missing count is not healthy. A later receipt with a passing result clears the incident.
Exit 0 stays exit 0. If the rule required records and the receipt says 0, the check fails. The email names that gap. It does not invent a cause.
A deploy clobbers your cron entry. The app responds 200. No one fires the scheduler. Your nightly emails stop.
GET /health 200 ok schedule:run · 17h ago
reports:generate finished clean. processed_records is 0. The rule wanted at least 1. Crontinel opens the incident anyway.
status completed · exit 0 processed_records 0 · failed
A worker process died. Your queue manager shows "running" because one worker is still up. Your billing queue is dead. No errors. No alerts. Just silence.
queue.manager running worker.emails · crashed
Any runtime posts one JSON receipt. Crontinel compares the count with the rule. The Laravel package attaches that receipt from the scheduler, and can add queue depth and Horizon freshness.
Per-worker status, paused detection, queue depth trend, failed job rate. Monitor every worker type - the moment one blinks, you know.
Zero is a real result. A receipt that omits the count is not treated as healthy.
curl, or the same JSON from Node. The ingest key is not the MCP key.
An alert on the same machine dies with the host. Crontinel reads the receipt after the process exits.
The zero-work alert and the later recovery both send by email. Slack and webhooks are not on the public card yet.
Status stays completed when the process exits 0. The outcome rule is a separate check.
status completed exit_code 0 processed_records 0 outcome failed
Cursor, Claude Code, or Codex can read the same incident. The packet says completion is not business success. It does not mark the job healthy.
Any runtime posts the same body. Use the ingest key, not an MCP key. The shell expands $CRONTINEL_INGEST_KEY.
# Node. curl sends this same JSON. status: "completed" exit_code: 0 processed_records: 0
The server keeps the process status. The outcome rule is separate. A minimum of 1 fails a zero count.
run completed · exit 0 outcome failed · actual 0
The email goes out with the model off. A later receipt that passes the rule resolves the incident.
processed_records 1 outcome passed
Run history keeps exit 0. The outcome column is the business result. On Laravel, queue depth and Horizon freshness show up only when that snapshot was reported.
| Task | Last run | Duration | Status |
|---|---|---|---|
| generate:daily-invoices | 2m ago | 1.82s | ok |
| dunning:send-reminders | 14m ago | 940ms | ok |
| reports:generate | 17m ago | 1.2s | exit 0 · 0 records |
| export:accounting-feed | 29m ago | 4.1s | ok |
| telemetry:roll-up | 1h 02m ago | 12.4s | slow |
| cleanup:stale-sessions | 3h ago | 220ms | ok |
| Queue | Depth | Oldest | Trend |
|---|---|---|---|
| default | 12 | 200ms | |
| invoices | 127 | 2m 04s | |
| emails | 6,413 | 12m 04s | |
| analytics | 88 | 400ms | |
| notifications | 3 | 80ms | |
Slack and customer webhooks stay off this page until a paid account receives the same failure and recovery.
What is checked today
We are checking paid billing and usage limits before opening paid signups.
For one app.
Starter, Pro, and Max are planned.
Their checkout flow and final usage terms are still under review.
See current availabilityPost the same HTTP body from curl, Node, Python, Sidekiq, or GitHub Actions. Unowned language SDKs are not a support claim. On Laravel, the Composer package attaches that receipt from the scheduler and can add queue depth and Horizon freshness.
Wrap the job, post the receipt, keep monitoring from failing the job.
Same JSON after the job finishes. No npm package required.
Script or Celery finally-block. No PyPI claim on this path.
Thin Ruby post after the job. No gem claim.
Secret + curl or Python after the job step.
Deep package: schedule attach, queue depth, and Horizon.
Same JSON from five runtimes. CRONTINEL_INGEST_KEY is the app ingest key. It is not an assistant key.
await fetch("https://app.crontinel.com/api/v1/ingest/cron", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CRONTINEL_INGEST_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
request_key: "run-1",
command: "reports:generate",
status: "completed",
exit_code: 0,
started_at: "2026-10-06T12:00:00Z",
finished_at: "2026-10-06T12:00:05Z",
outcomes: { metrics: { processed_records: 0 } },
}),
}); If you're comparing tools or looking for a specific failure mode, these are the strongest pages on the site.
See what cron monitoring covers, what queue monitoring covers, and why you need both in production.
Cron Monitoring Guide Complete guide to detecting missed runs, silent failures, worker stalls, and queue backpressure.Track paused supervisors, queue depth, and failing workers before the backlog becomes customer visible.
Catch delivery failures, retry storms, and stalled callback queues before customers notice.
Catch the moment schedule:run stops arriving, runs late, or silently skips a job.
The checked alert is email. Slack and webhooks are not listed here until a paid account receives the same failure and recovery.
Free to start, no card. Post one receipt. The email names a finished job that did no work.