Developers

Documentation

Everything you need to take a cron job from "it works on my machine" to "I will know within a minute when it doesn't".

Introduction

CronGuard is a heartbeat-based monitor for scheduled jobs. Your job pings a unique URL when it runs; if a ping doesn't arrive when it was expected to, CronGuard sends you (and your team) an alert. There's no agent to install and no inbound firewall hole to open — a single HTTP request from anywhere is enough.

The rest of this page walks through the full lifecycle: creating a monitor, pinging it, locking it down, getting alerted, pausing it, and sharing it with a team.

Core concepts

  • Monitor— a single named job (e.g. "Nightly backup") with an expected schedule.
  • Ping — an HTTP request your job makes to a unique URL each time it runs. GET or POST; either is valid.
  • Grace period — extra slack on top of the schedule before CronGuard considers the job overdue. Default is 15 minutes; configure per-monitor.
  • Status — computed on every read from the last ping: healthy, late (overdue but inside grace), down (overdue past grace) or paused.
  • Incident — the period from when a monitor went down until it recovered. Each incident gets one down-alert and one recovery email.

Creating a monitor

  1. Open the dashboard and click New monitor.
  2. Give it a recognisable name — this is what shows up in alerts.
  3. Pick a schedule: Every X minutes, Every X hours, Daily, or Weekly. It just needs to match how often your job actually runs.
  4. Optionally tune the grace period(1 minute to 24 hours). Pick a value that's wider than your worst-case job duration plus expected retry attempts.

When you save, CronGuard immediately gives you a ping URL of the form https://www.cronguard.app/api/ping/<monitor-id>.

Pinging from your job

Any successful HTTP request to the ping URL counts as a heartbeat. You can do it inline in a one-line wrapper around your cron job, or from inside your code at the end of a run.

# Simple "I'm alive" ping
curl -fsS "https://your-domain/api/ping/YOUR_MONITOR_ID"

# With timeout
curl -fsS --max-time 10 "https://your-domain/api/ping/YOUR_MONITOR_ID"

# Report how long the job took (in milliseconds)
START=$(date +%s%3N)
./my-script.sh
DURATION=$(($(date +%s%3N) - START))
curl -fsS -X POST \
  -H "Content-Type: application/json" \
  -d "{\"success\":true,\"duration\":$DURATION}" \
  "https://your-domain/api/ping/YOUR_MONITOR_ID"

# Report failure on error
./my-script.sh && curl -fsS "https://your-domain/api/ping/YOUR_MONITOR_ID" \
  || curl -fsS -X POST -d '{"success":false}' "https://your-domain/api/ping/YOUR_MONITOR_ID"
Replace YOUR_MONITOR_ID with a monitor ID from the list above.

A common pattern with crontab is to wrap the command so the ping only fires when the job succeeded:

# Run every 5 minutes; ping only on exit code 0
*/5 * * * * /usr/local/bin/backup.sh && curl -fsS -m 10 \
  https://www.cronguard.app/api/ping/<monitor-id> > /dev/null

Reporting success & failure

A plain GET or POST is enough to record a successful heartbeat. If you want more detail in the dashboard, send a JSON body with POST:

// Success, with how long the job took (ms)
POST /api/ping/<monitor-id>
{ "success": true, "duration": 1234 }

// Explicit failure — CronGuard alerts immediately,
// without waiting for the grace period to expire.
POST /api/ping/<monitor-id>
{ "success": false, "message": "DB unreachable" }
  • success — boolean. Missing means true.
  • duration— integer milliseconds, 0–86 400 000. Used for the duration chart on the monitor page.
  • message — free-form text up to 500 characters. Shows up on the activity row and in the failure alert email.

Securing the ping URL

Ping URLs are unguessable by default, but they are still public — anyone with the URL can mark your job as healthy. For anything important, add one or more required headers to the monitor.

  1. Open the monitor, expand Required headers.
  2. Add a header name (e.g. X-Ping-Token) and a secret value.
  3. In your job, send that header. Pings without the right value get rejected with 401 Authentication failed.

Header names are case-insensitive. Values are compared with timing-safe equality, so an attacker can't use response timing to brute-force the secret.

curl -fsS -m 10 \
  -H "X-Ping-Token: <secret>" \
  https://www.cronguard.app/api/ping/<monitor-id>

Alerts & incidents

Every minute, CronGuard checks each monitor. If a healthy or late monitor has crossed its grace period, the monitor flips to down and a down alert goes out by email. As soon as the next successful ping arrives, the monitor goes back to healthy and a recovery alert closes the incident.

Alerts go to the monitor's owner and to every enabled team member (see Teams & permissions). You won't get spammed — one email per state transition, not one per minute.

Pausing a monitor

Planned downtime, a migration, or a temporary job removal — pause the monitor so it doesn't page anyone. A paused monitor:

  • Still accepts pings (they're recorded for history).
  • Is never considered late or down.
  • Optionally auto-resumes at a timestamp you choose — useful for maintenance windows.

From the dashboard, click Pause on a monitor, optionally add a reason and an until time. Resume manually with Resume or just wait — the cron job ticking once a minute will auto-resume any monitor whose pausedUntil has passed.

Teams & permissions

The Team plan adds a team workspace. The owner creates a team and shares an invite URL of the form /invite/<token>. Anyone who signs in with that link joins the team in a pending, read-only state.

The owner can then, per member:

  • Enable— give them dashboard access. Disabled members see an "Access Disabled" page.
  • Can edit — grant write access (create, edit, delete, pause, reorder). Without this they have read-only access.
  • Remove — kick them out. Their monitors stay with the team.

The invite token can be regenerated at any time, which invalidates the old URL.

Data retention

Pings are kept according to the workspace plan. Older pings are deleted nightly at 03:00 UTC; only the 75 most recent pings per monitor are kept regardless of age.

PlanPing historyMonitors
Free7 days5
Pro30 days50
Team90 daysUnlimited

Pro and Team can export ping history to CSV from the monitor detail page.

Plan limits & rate limits

The ping endpoint is rate-limited at 5 requests / minute per monitor. That's well above the highest schedule CronGuard accepts (one ping per minute) and is there purely to stop misconfigured jobs from hammering the ingest. Hitting the limit returns 429 Too Many Requests with the standard Retry-After header.

Team management calls (inviting, enabling, removing members) are also rate-limited to keep abuse in check — 20/min per user for member operations, 10/min per IP for the invite flow.

Troubleshooting

My monitor never goes green

Verify the ping URL by running the curl from the dashboard locally. If you get 404, the monitor id is wrong. If you get 401, you're missing a required header. Anything 2xx counts as a healthy ping.

The monitor went down but my job ran fine

Three usual suspects:

  • The schedule on the monitor is tighter than the actual cron schedule. Loosen it, or raise the grace period.
  • The ping is happening before the work — and the work failed silently. Move the ping to after the work and only on success.
  • Egress from the job's network is being blocked. Try a manual curl from the same host.

I'm not getting alert emails

Check spam, then check that your team membership is enabled. Down alerts only go to enabled members. If still nothing, email support@cronguard.appwith the monitor id and we'll trace it.

Still stuck?
Email support@cronguard.app with a description and a monitor id and we'll get back to you within one working day.
← Back to home