Help & Documentation
Everything you need to set up, integrate, and get the most out of CronDoctor.
On this page
Getting Started
Integration
- Ping Integration Guide
- Language & Platform Examples
- Rate Limits
- Endpoint Protection
- Signal Endpoint Lifecycle
Intelligence
Notifications
Dashboard
Account
How CronDoctor Works
CronDoctor listens for two signals from your jobs — whether cron jobs, Lambda functions, data pipelines, or any scheduled task. Signal 1 — the heartbeat — tells you when something is wrong and catches performance drift before it becomes an outage. Signal 2 — error context — tells you why it failed and how to fix it. Each signal is valuable on its own. Together, they give you the full story in a single alert.
Under the hood, it works like a "dead man's switch": your job pings CronDoctor when it runs. If the ping doesn't arrive on time, CronDoctor knows something is wrong. The schedule you set tells CronDoctor when to expect the ping — it doesn't run or trigger your job.
Key concepts
- Monitor — A monitor represents one of your jobs inside CronDoctor — one monitor per job. Each monitor has its own schedule, ping endpoint, and alert settings.
- Ping — A message your job sends to CronDoctor each time it runs. The delivery mechanism for signals.
- Signal 1 — The heartbeat. Your job telling CronDoctor "I ran" — and optionally, how long it took.
- Signal 2 — Error context. Your job telling CronDoctor "something went wrong" — exit codes, stderr, or stack traces that explain why it failed.
Your job pings CronDoctor (Signal 1)
Add a curl command to your job. When it runs, it sends a heartbeat ping to your unique endpoint. Add duration and CronDoctor learns what ‘normal’ looks like.
Schedule compliance checks run every 60 seconds
CronDoctor compares each job’s expected ping time against the actual last ping. If a ping is overdue (past the grace period), the job’s status changes to "late" or "down".
Smart alerting classifies severity
Not every missed ping deserves a 2 AM wake-up call. CronDoctor classifies alerts as critical, warning, or info — and suppresses noise based on adaptive thresholds and history.
AI diagnoses the root cause (Signal 2)
When your ping includes error context — exit codes, stderr, or stack traces — CronDoctor’s AI analyzes the failure and provides a plain-English diagnosis with a suggested fix.
You get notified
Alerts are sent via email, Slack, Discord, Microsoft Teams, or PagerDuty — with the diagnosis included so you can fix the problem immediately.
Why two signals matter
Most monitoring tools only listen for the heartbeat. They can tell you a job is down, but not why. CronDoctor combines both signals so your alerts include the root cause and a suggested fix — not just "check-in missed." One alert, complete context, immediate action.
Cron Expression Basics
A cron expression is five fields that specify when a job runs — minute, hour, day of month, month, and day of week. CronDoctor uses cron expressions to know when to expect pings from your jobs.
Cron Expression Format
│ ┌───── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌───── month (1-12)
│ │ │ │ ┌───── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *
Common Patterns
| Expression | Meaning |
|---|---|
| * * * * * | Every minute |
| */5 * * * * | Every 5 minutes |
| 0 * * * * | Every hour (at minute 0) |
| 0 3 * * * | Every day at 3:00 AM UTC |
| 0 0 * * 0 | Every Sunday at midnight UTC |
| 0 0 1 * * | First day of every month at midnight |
| 30 2 * * 1-5 | Weekdays at 2:30 AM UTC |
Timezones & UTC
All schedules in CronDoctor are evaluated in UTC. If your server or machine uses a different timezone, convert your local time to UTC when telling CronDoctor your job's schedule.
Example: Your Mac runs a job at 10:30 AM US Eastern (30 10 * * * in your local crontab). US Eastern is UTC−5, so tell CronDoctor the schedule is 30 15 * * * (15:30 UTC).
Daylight saving tip: During DST your ping arrives an hour early — that's fine. CronDoctor only alerts on missing pings, not early ones. Use the later UTC offset (standard time) so you're covered year-round.
Coming from another platform?
Paste your Quartz, AWS EventBridge, or Spring expression — CronDoctor converts it automatically. Quartz's ? and seconds field are handled automatically. Just paste and go.
| @daily | → | 0 0 * * * |
| @hourly | → | 0 * * * * |
| @weekly | → | 0 0 * * 0 |
| @monthly | → | 0 0 1 * * |
| @yearly | → | 0 0 1 1 * |
Monitoring Your First Job
Tell CronDoctor about your job
From the dashboard, click "Tell CronDoctor about a job." Give it a name (e.g., "nightly-backup"), tell CronDoctor whether it runs on a cron schedule or at a fixed interval, enter the schedule, and set how late is still okay. The default grace period of 5 minutes works well for most jobs.
Copy the ping URL
After setup, you'll see your unique ping URL. It looks like: https://crondoctor.com/api/v1/ping/YOUR_MONITOR_ID
Add the ping to your job
Add a curl command at the end of your job's script. The simplest version is just a bare ping. For more intelligence, add duration (Signal 1) or error context like exit codes and stderr (Signal 2). See the Integration Guide below for examples.
Wait for the first ping
Your job will show "NEW" until the first ping arrives. Once it does, the status changes to "UP" and CronDoctor starts tracking against your schedule.
Schedule types
- Cron — For jobs that run on a cron schedule. You enter a cron expression and CronDoctor expects pings at those times.
- Heartbeat — For jobs that run at a fixed interval (e.g., every 300 seconds). No cron expression needed — just set the interval.
Grace period
The grace period is how long CronDoctor waits after the expected ping time before considering the job late. A grace period of 5 minutes (300 seconds) means: if your job is scheduled for 3:00 AM UTC, CronDoctor won't alert until 3:05 AM UTC. This prevents false alarms from scheduling jitter, slow network connections, or brief system load spikes.
Ping Integration Guide
CronDoctor supports three levels of integration, building toward two powerful signals:
Simple ping
Heartbeat monitoring — detects missed and late jobsDetects missed and late jobs. CronDoctor knows when it ran, but not whether it succeeded or how long it took.
With exit code & duration
Adaptive thresholds — learns your job's normal runtime and catches driftSend duration to enable adaptive thresholds. CronDoctor learns your job's normal runtime and flags anomalies — even when the job "succeeds." Add exit code to detect non-zero failures.
What's $?? It's the exit code of the last command. 0 means success, anything else means failure. The shell captures it automatically — just make sure the curl line comes right after your script.
Rich payload
AI diagnosis — tells you why it failed and suggests the fixSend exit code, duration, and stderr to unlock AI root cause diagnosis. CronDoctor tells you why it failed and gives you the commands to fix it.
What each data field unlocks
- Ping alone — Standard monitoring: missed and late job detection
- + Duration — Signal 1 Adaptive thresholds: learns normal runtime, flags performance anomalies
- + Exit code — Failure detection: non-zero exit codes trigger alerts, signal codes (137 = OOM killed) provide context
- + stderr — Signal 2 AI root cause diagnosis: error output like "disk full" lets the AI pinpoint the problem and suggest a fix
- + stdout — Additional context for the AI when stderr alone isn't enough
Start with a simple ping. Add more data as you need deeper insights. All capabilities are free on every plan.
Wrapper script vs. embedded ping
The examples above use shell wrapper scripts, but you can also embed the ping directly in your application code using an HTTP POST. This gives you more control — you can send specific error messages from your catch/except blocks and measure duration more precisely.
Rule of thumb: Use a wrapper script for jobs you can't modify (legacy scripts, third-party tools, compiled binaries). Embed the ping in jobs where you own the code.
POST payload fields
| Field | Type | Description |
|---|---|---|
| signal | string | start, end, complete, fail, or warn |
| exit_code | integer | Process exit code (0 = success) |
| duration_ms | number | Duration in milliseconds |
| stderr | string | Error output (last 100 lines recommended). Sent to AI for diagnosis on failure. |
| stdout | string | Standard output (last 50 lines recommended). Sent to AI for diagnosis on failure. |
| message | string | Short custom message |
GET requests use ?duration=N in seconds. POST requests use duration_ms in milliseconds.
Rate Limits
The ping endpoint accepts up to 10 requests per second per monitor. Rate-limited requests still return 200 OK with the X-CronDoctor: rate-limited header — your job won't see an error.
In practice, no correctly-configured job should ever hit this limit. It exists to prevent runaway retry loops from overwhelming the ingestion pipeline. If you're pinging more than 10 times per second, consider using the signal endpoint (start/end) pattern instead.
Endpoint Protection Pro
Protect your ping endpoints from unauthorized submissions. When enabled, pings must include an authentication token in the X-CronDoctor-Token header.
How to enable: Open any job → Edit → scroll to “Endpoint Protection” → click “Enable.” A token will be generated and shown once. Copy it and add it to your ping commands.
curl -s -H "X-CronDoctor-Token: your-token-here" https://crondoctor.com/api/v1/ping/YOUR_MONITOR_IDToken rotation: Click “Rotate Token” in the edit modal to generate a new token. The old token stops working immediately. Update your jobs before rotating.
Silent rejection: Unauthorized pings still return 200 OK — they won't break your scripts during migration. But no ping data is recorded. Check the X-CronDoctor: unauthorized response header to verify your token is correct.
Language & Platform Examples
Copy-paste examples for common languages and platforms. Replace YOUR_MONITOR_ID with your actual ping endpoint ID from the job detail page.
Python
Node.js
cURL (one-liner for crontab)
Important: Use ; (semicolon), NOT &&. With &&, the ping is skipped when your script fails — which is exactly when you need it most. The || true ensures the curl itself never causes a non-zero exit for your cron entry.
Go
PHP
Ruby
Java
C#
PowerShell
Kubernetes CronJob
Uses the start/end/fail signal pattern so CronDoctor can track job duration automatically. Set restartPolicy: Never to prevent Kubernetes from restarting failed jobs (let CronDoctor alert you instead).
Docker (wrapper script)
Schedule this wrapper script with cron or systemd timer. Don't put the ping inside the Dockerfile — the ping should run on the host, outside the container.
Signal Endpoint Lifecycle
Use the signal endpoints to tell CronDoctor exactly what happened — success, failure, or in-progress. The start signal is optional. Most jobs only need end or fail.
Signal types
- end or complete — Send when your job finishes successfully. Include
duration_msorexit_codefor richer intelligence. - fail — Send when your job fails. Include
stderrfor AI-powered root cause diagnosis. - warn — Send when your job succeeds but something isn't right. The job completed, but it encountered problems worth knowing about — skipped records, degraded performance, permissions issues. Sets the monitor to a WARNING state. (Pro plan receives alert notifications)
- start — (Optional) Send when your job begins. Useful for detecting jobs that start but never finish — if no end/fail signal arrives, the compliance check flags the job as late or down.
Tip: You probably don't need the start signal
If your job already knows how long it ran (most do), just send end or fail with the duration included. CronDoctor gets the same data — timing, exit code, error output — without the extra HTTP call.
Use start only when you need to detect hung jobs — ones that begin but never finish. The start signal lets CronDoctor know the job is running, so if end/fail never arrives, it flags the problem.
Example: end-only (simplest)
This gives CronDoctor both signals in a single call — timing data (Signal 1) and error context (Signal 2) — without needing a separate start ping.
Example: start + end workflow (for hung job detection)
Use this pattern when you need to detect hung jobs. The start signal lets CronDoctor know the job is running — if end/fail never arrives, the compliance check flags it.
Smart Alerting & Adaptive Thresholds
This is what makes CronDoctor different
Every other monitoring tool does the same thing: missed ping = alert. Period. That binary approach creates alert fatigue — you get paged at 3 AM for a 10-second blip that self-resolves, and eventually you start ignoring alerts entirely.
CronDoctor has three features no competitor offers: AI root cause diagnosis, adaptive thresholds, and noise suppression. These are included free on every plan.
Baseline & Adaptive Thresholds
CronDoctor learns what "normal" looks like for each of your jobs. No configuration required — the defaults work well for most jobs.
How it works
- Your first 10 pings with duration data establish a baseline
- CronDoctor calculates the P95 duration + 20% buffer as your baseline (these are the defaults — see below for customization)
- If a future job exceeds this threshold, it triggers a "slow" warning — even if the job "succeeded"
- The threshold updates continuously using the last 50 pings with duration data
Example
Your nightly backup normally takes 20-35 seconds. CronDoctor calculates a P95 of 33s, adds 20%, and sets the baseline at 39.6 seconds. One night the backup takes 4 minutes and exits 0 (success). A binary monitor sees "success" and says nothing. CronDoctor flags it as a WARNING — because something changed.
The baseline is shown on the job's detail page. It shows "Learning..." until 10 pings with duration data are collected. To enable it, send duration with your pings (see the Ping Integration Guide).
Customization (Pro plan)
Pro users can customize the baseline sensitivity per monitor. Choose from presets or set custom values:
- Default — P95 percentile, 20% buffer (works well for most jobs)
- Sensitive — P75 percentile, 10% buffer (flags smaller deviations)
- Tolerant — P99 percentile, 50% buffer (reduces alerts for variable jobs)
- Custom — Set your own percentile (50-99) and buffer (0-100%)
Free and Starter plans use the default baseline (P95 + 20% buffer), which provides a good balance for most workloads.
Severity Classification
Every alert is classified into one of three levels:
- CRITICALJob is down with multiple consecutive misses, or a failure with a non-zero exit code
- WARNINGFirst missed ping, job running significantly slower than its baseline, or job completed with warnings
- INFOJob recovered after being down, or minor deviation from expected behavior
Job Health Warnings Pro
Sometimes a job succeeds but something isn't right — skipped records, degraded performance, permissions issues. CronDoctor can detect these situations and set the monitor to a WARNING state.
Two ways to trigger a warning
- Explicit: Send a
/warnsignal — your job decides when to warn - Inferred (Pro only): A job exits with code 0 but has stderr output. CronDoctor infers something went wrong.
All plans accept warning data and show the WARNING status. Pro plan users also receive alert notifications.
How exit code + error output interact
| Exit Code | Error Output | Result |
|---|---|---|
| Non-zero | Any | DOWN — always an error, full AI diagnosis |
| 0 (success) | Has stderr | WARNING — if toggle is on, full AI diagnosis |
| 0 (success) | No stderr | UP — healthy, no action |
"Detect problems in successful jobs" toggle
This per-monitor toggle controls only the inferred warning — exit code 0 with stderr output. It has no effect on jobs that fail (exit code non-zero), which are always treated as errors regardless of this setting.
When enabled, jobs that exit with code 0 but produce error output will undergo a full AI diagnosis. Disable it if your job writes informational output to stderr instead of stdout.
The toggle is on by default for Pro plan monitors. Explicit /warn signals always trigger a warning regardless of this setting.
Noise Suppression
CronDoctor targets 60-80% noise reduction compared to binary monitoring:
- No re-alerting: A monitor that's already "down" doesn't send a new alert every 60 seconds. You get one alert when it goes down, and one when it recovers.
- Grace periods: Configurable per monitor. A job that runs 30 seconds late due to system load doesn't trigger an alert.
- Severity-based routing: Critical alerts go everywhere. Info-level alerts don't page your on-call.
Root Cause Diagnosis
When your ping includes exit codes and stderr output, CronDoctor analyzes the failure and tells you exactly what went wrong — with a suggested fix to help you start troubleshooting.
What other tools show
❌ "nightly-backup: check-in missed. Expected at 03:00 UTC."
What CronDoctor shows
✅ "Disk full on /var/data — PostgreSQL could not write WAL segments. The backup process stalled waiting for disk space, then timed out."
Suggested fix: df -h /var/data && sudo apt autoremove && sudo journalctl --vacuum-size=500M
87% confidence
How it works
- Rich errors (3+ lines of stderr, like stack traces) go directly to GPT-4o-mini for specific diagnosis
- Simple errors (exit codes, single-line stderr) check a knowledge base cache first — instant, zero-cost responses for common patterns
- A confidence score is included with every diagnosis so you know how much to trust it
- All diagnoses include a disclaimer — verify against raw error output before acting
Getting better diagnoses
The AI can only work with what you send. To get the best diagnoses:
- Send stderr — this is the most valuable data for diagnosis
- Include the exit code — signal codes like 137 (OOM killed) or 143 (SIGTERM) provide immediate context
- Capture the last 100 lines of stderr, not just the last line — stack traces need context
Diagnosis feedback
Each diagnosis on the job detail page has thumbs up/down buttons. Your feedback helps improve the knowledge base and future diagnoses for similar errors.
Your data privacy
- CronDoctor uses the OpenAI API, not the consumer ChatGPT product
- Per OpenAI's API data usage policy, your data is not used to train AI models
- API data is retained by OpenAI for a maximum of 30 days for abuse monitoring, then deleted
- Only job-relevant context is sent: monitor name, exit code, stderr/stdout snippets, and schedule. No personal information (email, payment details, IP addresses) is ever sent
- Common error patterns are handled by a local knowledge base — those never leave CronDoctor's servers
See our Privacy Policy for full details.
Alert Channels Setup
CronDoctor supports 5 notification channels. Configure them in Settings. Channel availability depends on your plan.
Alerts are sent to your account email by default. You can set a separate alert email in Settings (useful for routing to a shared inbox or PagerDuty email integration).
Important: Alert emails are only sent to verified email addresses. If you set a separate alert email, you'll receive a verification link that must be clicked before alerts start.
Slack
Starter+Alerts appear as rich Block Kit messages with severity colors, diagnosis details, and a "View Details" button.
Setup
- Go to api.slack.com/apps and create a new app
- Enable "Incoming Webhooks" and add a webhook to your channel
- Copy the webhook URL (starts with
https://hooks.slack.com/) - Paste it in CronDoctor Settings under "Slack Webhook URL"
Discord
ProAlerts appear as rich embeds with severity colors and clickable monitor titles.
Setup
- In your Discord server, go to Channel Settings → Integrations → Webhooks
- Click "New Webhook" and name it "CronDoctor"
- Copy the webhook URL (starts with
https://discord.com/api/webhooks/) - Paste it in CronDoctor Settings under "Discord Webhook URL"
Microsoft Teams
ProAlerts appear as Adaptive Cards with "View Details" action buttons.
Setup
- In your Teams channel, click the "..." menu → Connectors (or Workflows)
- Add an "Incoming Webhook" connector
- Name it "CronDoctor" and copy the URL
- Paste it in CronDoctor Settings under "Teams Webhook URL"
PagerDuty
ProAlerts create PagerDuty incidents with severity mapping and direct links back to CronDoctor.
Setup
- In PagerDuty, go to Services → your service → Integrations
- Add a new integration using "Events API v2"
- Copy the Integration Key (routing key)
- Paste it in CronDoctor Settings under "PagerDuty Routing Key"
Understanding the Dashboard
The dashboard is your at-a-glance view of all your jobs. Here's what each piece means:
Job statuses
- UPPings are arriving on schedule. Everything is working.
- LATEThe expected ping hasn't arrived and the grace period has been exceeded. One missed ping.
- DOWNMultiple consecutive pings have been missed, or the job reported a failure (non-zero exit code).
- NEWJust added — waiting for the first ping from your job.
- PAUSEDPaused — no compliance checks or alerts. Useful during maintenance.
Summary bar
At the top of the dashboard you'll see your job count (used / plan limit), how many are down or new, and the "Smart alerting" counter showing how many alerts were suppressed today. A high suppression count means CronDoctor is saving you from alert fatigue.
Sections
Monitors are grouped by priority:
- NEEDS ATTENTION — Jobs that have missed multiple pings. Investigate immediately.
- RUNNING SLOW — Jobs that succeeded but took longer than their baseline. May indicate emerging problems.
- HEALTHY — Jobs that are up and running normally.
- WAITING FOR PING — New jobs that haven't received their first ping yet.
Timeline bars
Each monitor shows a timeline of recent activity. Gray bars are successful runs, red means failure or missed ping, and amber means warning. Short red bars at minimum height indicate missed pings — the job never ran. Bar height encodes duration (taller = longer run). The success rate next to each monitor factors in both failures and missed pings, showing true availability.
Job Detail Page
Click on any job from the dashboard to see its detail page. Here's what each section shows:
Stats cards
- Last heard from — When the most recent ping was received. "just now" means pings are flowing.
- Typical runtime — Average runtime of your job across recent pings. Only shows if you send duration data (Signal 1 integration or above).
- Baseline — CronDoctor's learned sense of "normal" for this job, calculated from your last 50 pings. Defaults to P95 + 20% buffer. Pro users can customize sensitivity per monitor. Shows "Learning..." until 10 pings with duration data arrive.
- Pings — Total number of pings received within your plan's history window.
- Alerts filtered — Percentage of potential alerts that were suppressed instead of sent. A higher number means CronDoctor is saving you from alert fatigue.
Tabs
- Ping History — Every ping received, with signal type, exit code, and duration. Gray dot = success, red = failure, amber = warning, blue = started.
- Alerts — All alerts generated for this job, with severity, reason, and timestamps.
- Diagnoses — CronDoctor's root cause analyses for failures. Each includes a confidence score, summary, and suggested fix. Use the thumbs up/down to provide feedback.
Actions
- Edit — Change the job name, schedule, or grace period.
- Pause — Temporarily stop compliance checks and alerts. Useful during planned maintenance. Pings are still recorded but won't trigger alerts.
- Delete — Stop watching this job and permanently remove all its data.
Status Badges
Each job has a public status badge URL you can embed in your README, wiki, or status page. The badge updates in real-time and shows the current status.
How to use
Find the badge URL on the job's detail page (labeled "Status badge"). Embed it in Markdown:
The badge is public and doesn't require authentication. It returns an SVG image that shows UP (blue), DOWN (red), LATE (yellow), or NEW (gray).
Plans & Billing
AI diagnosis, smart alerting, and adaptive thresholds are included on every plan — including free. Plans differ in monitor count, history retention, and notification channels.
| Feature | Free | Starter ($19/mo) | Pro ($49/mo) |
|---|---|---|---|
| Jobs you can watch | 5 | 20 | 100 |
| Ping history | 7 days | 30 days | 90 days |
| Email alerts | ✓ | ✓ | ✓ |
| Slack alerts | — | ✓ | ✓ |
| Discord / Teams / PagerDuty | — | — | ✓ |
| Smart alerting & adaptive thresholds | ✓ | ✓ | ✓ |
| Diagnosis | ✓ | ✓ | ✓ |
| Custom adaptive thresholds | — | — | ✓ |
| Endpoint protection | — | — | ✓ |
Upgrading or downgrading
Go to Settings to change your plan. Upgrades take effect immediately. Downgrades take effect at the end of your current billing cycle. If you downgrade and have more monitors than the new plan allows, you'll need to delete or pause jobs to fit within the limit.
Cancellation
You can cancel your subscription anytime from Settings. Your paid features remain active until the end of the current billing period, then your account reverts to the free plan. Your jobs and data are preserved, but any jobs above the free tier limit are automatically paused.
History retention
Pings, alerts, and diagnoses older than your plan's history window are automatically cleaned up once per hour. Free: 7 days, Starter: 30 days, Pro: 90 days. If you downgrade, data older than the new retention window will be cleaned up in the next hourly cycle.
Troubleshooting & FAQ
My job is stuck on "NEW"
A job stays in the "new" state until CronDoctor receives its first ping. Try running the curl command from your terminal to verify the endpoint works. Check that you're using the correct ping endpoint ID in the URL. The format is: https://crondoctor.com/api/v1/ping/YOUR_MONITOR_ID
My job shows DOWN but it's running fine
This usually means the ping isn't reaching CronDoctor. Common causes:
- The curl command in your job has a typo in the ping endpoint ID
- Your server can't reach
crondoctor.com(firewall, DNS, or network issue) - The curl command is placed before a long-running step — if the script takes too long, the next expected ping time passes
- A CDN or proxy is caching the GET request — add a cache-buster like
?_t=$(date +%s)
Test manually: curl -v https://crondoctor.com/api/v1/ping/YOUR_MONITOR_ID
I'm not receiving email alerts
Check your alert email address in Settings. Also check your spam folder — the first few emails from a new sender sometimes end up there. CronDoctor sends from alerts@send.crondoctor.com. If you set a separate alert email, make sure you've verified it by clicking the link in the verification email. Only verified addresses receive alerts.
The diagnosis says "insufficient data"
CronDoctor needs failure data to diagnose problems. Send exit codes, duration, and stderr with your pings (see the Signal 1 and Signal 2 examples in the Integration Guide above). A basic heartbeat ping only tells CronDoctor that the job ran — not whether it succeeded.
Adaptive threshold shows "Learning..."
The adaptive threshold needs at least 10 pings with duration data to activate. Make sure you're sending the duration parameter with your pings (Signal 1 integration or above). For a job that runs every 5 minutes, it takes about 50 minutes to collect enough data. For a daily job, it takes 10 days.
My job is slow but I'm not getting slow alerts
CronDoctor only generates slow alerts when the job duration is meaningful enough to warrant attention:
- The job must take at least 5 seconds to complete — faster jobs have natural millisecond-level variance that isn't operationally meaningful
- The actual duration must exceed the baseline by at least 2 seconds — small absolute differences aren't worth alerting on even if the relative multiplier looks high
For example, a job that normally takes 50ms and completes in 300ms is technically 6x the baseline, but the 250ms difference has no operational impact. CronDoctor focuses on slowdowns that actually matter — like a 30-second job taking 2 minutes.
Duration shows 0ms in ping history
If you're sending duration as a GET query parameter (?duration=N), the value should be in seconds (e.g., duration=4.5 for 4.5 seconds). Very fast jobs (under 1 second) should still send fractional values like 0.1. If using the POST body, send duration_ms in milliseconds.
How do I change my job's schedule?
Click on the job from the dashboard, then click the "Edit" button in the top right. You can update the name, cron expression (or heartbeat interval), and grace period.
Why am I getting alerts right after adding a job?
New jobs start in the "new" state and won't trigger alerts until after the first ping arrives. After the first ping, CronDoctor starts tracking based on your schedule. If the next expected ping doesn't arrive within the grace period, you'll get an alert.
Can I monitor jobs that don't use cron?
Yes. Use the "heartbeat" monitor type instead of "cron." Set the interval in seconds (e.g., 300 for a job that runs every 5 minutes). CronDoctor will expect a ping at that interval. This works for Windows Task Scheduler, systemd timers, Kubernetes CronJobs, AWS EventBridge rules, or any scheduler.
My ping endpoint returns an error
The ping endpoint is designed to always return 200 OK. If you're seeing errors, check that the URL is correct and includes your full ping endpoint ID. If you get a 404, the ID doesn't exist — double-check it from the job's detail page.
How do I test that alerts are working?
The easiest way is to send a failure ping manually from your terminal:
This sends a non-zero exit code, which immediately marks the job as "down" and triggers an alert through all your configured channels. Send a normal ping afterward (exit_code=0 or no exit code) to recover it.
My Slack/Discord/Teams webhook isn't receiving alerts
Common causes:
- The webhook URL was regenerated or deleted in the channel settings — re-copy the URL and update it in Settings
- The URL format is wrong — Slack URLs start with
https://hooks.slack.com/, Discord withhttps://discord.com/api/webhooks/ - Your plan doesn't include the channel — Slack requires Starter ($19/mo), Discord/Teams/PagerDuty require Pro ($49/mo)
- The bot/connector was removed from the channel — re-add it in the channel settings
To verify, trigger a test alert (see FAQ above) and check whether the alert appears in your Alerts feed. If the alert is there but the webhook didn't fire, the URL is likely invalid or expired.
I changed my cron schedule but alerts seem wrong
When you update a job's schedule, CronDoctor immediately recalculates the next expected ping based on the new expression. The change takes effect right away — there is no delay. If alerts still seem off, check that the new cron expression matches what you intend (CronDoctor shows a human-readable description below the input). Remember that all schedules are evaluated in UTC, not your local timezone.
How do I pause monitoring during maintenance?
Click on the job from the dashboard, then click the "Pause" button in the top right. While paused, no compliance checks run and no alerts are sent. Pings are still recorded but won't trigger state transitions. Click "Resume" when maintenance is done — CronDoctor recalculates the next expected ping from the current time so you won't get a false alarm for the gap.
Still have questions? Email us at support@crondoctor.com