Home/Documentation

Documentation

Complete guide to monitoring your cron jobs with CronOwl

What is CronOwl?

CronOwl is a dead man's switch monitoring service for your scheduled tasks and cron jobs. Instead of actively checking if your servers are up, CronOwl waits for your jobs to "check in" by sending a simple HTTP request (ping).

If a ping doesn't arrive within the expected time window, CronOwl knows something is wrong and immediately alerts you via email, push notifications, Telegram, or webhooks.

Perfect for monitoring:

  • Database backups
  • Data synchronization jobs
  • Report generation
  • Email queue processing
  • Scheduled API calls
  • Cleanup and maintenance tasks
  • Payment processing
  • Any scheduled task that must run reliably

Why "dead man's switch"? The concept comes from safety devices that trigger when the operator becomes incapacitated. Similarly, CronOwl triggers alerts when your job stops "checking in" — meaning something has gone wrong.

Quick Start

1

Create a check

Go to your Dashboard and click "New Check". Give it a descriptive name and set the expected schedule.

Example schedules:

  • every 5 minutes — For health checks
  • every hour — For hourly reports
  • every day at 2am — For nightly backups
  • 0 2 * * * — Custom cron expression
2

Copy your ping URL

Each check gets a unique URL. Copy it from the dashboard — it looks like this:

https://cronowl.com/api/ping/abc123xyz
3

Add ping to your script

Add a single curl request at the end of your cron job. When CronOwl receives the ping, it knows your job ran successfully.

backup.shbash
#!/bin/bash
set -e

# Your backup logic
pg_dump mydb > /backups/mydb_$(date +%Y%m%d).sql

# Ping CronOwl on success
curl -fsS --retry 3 https://cronowl.com/api/ping/YOUR_SLUG
4

Get alerts when things break

If your job doesn't ping within the expected time + grace period, we'll alert you immediately:

EmailInstant alerts
PushMobile & web
TelegramBot messages
WebhookSlack, Discord

How It Works

1. Your job runs and pings CronOwl

At the end of your script, make an HTTP request to your unique ping URL. CronOwl records the timestamp, duration, and any metadata you send.

2. CronOwl tracks the schedule

Based on your configured schedule (e.g., "every hour"), CronOwl knows when the next ping should arrive. It continuously monitors all your checks.

3. Grace period buffer

Jobs don't always run at exactly the same time. The grace period (1-60 minutes) gives your job extra time before CronOwl considers it late.

4. Alert on missing ping

If the expected time + grace period passes without a ping, CronOwl immediately sends alerts through all your configured channels.

5. Recovery notification

When a previously "down" check receives a ping again, CronOwl sends a recovery notification so you know the issue is resolved.

Status States

New

Check created but no pings received yet. Waiting for first ping.

Up

Pings arriving on schedule. Everything is working correctly.

Down

Ping is late. Expected time + grace period has passed without a ping.

Schedules & Cron Expressions

Preset Schedules

Choose from common intervals for quick setup:

every minute
every 2 minutes
every 5 minutes
every 10 minutes
every 15 minutes
every 30 minutes
every hour
every 2 hours
every 6 hours
every 12 hours
every day
every week

Custom Cron Expressions

For precise control, use standard cron syntax:

* * * * *
minute
(0-59)
hour
(0-23)
day
(1-31)
month
(1-12)
weekday
(0-6)
ExpressionDescription
*/5 * * * *Every 5 minutes
0 * * * *Every hour at minute 0
0 2 * * *Every day at 2:00 AM
0 9 * * 1-5Every weekday at 9:00 AM
0 0 1 * *First day of every month at midnight
30 4 * * 0Every Sunday at 4:30 AM

Timezone Support

All schedules are evaluated in your selected timezone. Supported timezones include:

UTC
America/New_York
America/Los_Angeles
America/Chicago
Europe/London
Europe/Paris
Europe/Moscow
Asia/Tokyo
Asia/Shanghai
Asia/Dubai
Australia/Sydney
Pacific/Auckland

And 20+ more timezones available in the dashboard.

Grace Period

The grace period (1-60 minutes) is extra time added after the expected ping time before marking a check as "down". This accounts for:

  • Jobs that take variable time to complete
  • Network latency or temporary connectivity issues
  • Server load causing slight delays

Example: If your job runs at 2:00 AM with a 5-minute grace period, CronOwl won't alert until 2:05 AM if no ping is received.

Notifications

CronOwl sends notifications through multiple channels. Configure them in your Settings.

Email

All plans

Receive detailed email alerts for down, recovery, and slow job events. Emails are sent to your account email address.

Enable in Settings → Notifications → Email notifications

Push Notifications

All plans

Get instant push notifications on your phone or desktop. Works even when the browser is closed. CronOwl is a PWA — install it on your home screen for the best experience.

Enable in Settings → Notifications → Push notifications (requires browser permission)

Telegram

All plans

Receive alerts directly in Telegram. Link your account with a simple verification code.

How to connect:

  1. 1. Open @CronOwlBot in Telegram
  2. 2. Copy the 6-digit code from Settings → Telegram
  3. 3. Send the code to the bot
  4. 4. Done! You'll receive alerts in Telegram

Webhooks

Starter & Pro plans

Send alerts to any HTTP endpoint. Includes native formatting for Slack and Discord.

Slack

Use a Slack Incoming Webhook URL. Messages are formatted with colored attachments.

https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX

Discord

Use a Discord Webhook URL. Messages use rich embeds with colors.

https://discord.com/api/webhooks/000000000000000000/XXXXXXXX

Generic Webhook

Any other URL receives a JSON POST request:

Payloadjson
{
  "event": "check.down",
  "check": {
    "id": "abc123",
    "name": "Database Backup",
    "slug": "db-backup-xyz",
    "status": "down"
  },
  "timestamp": "2024-01-20T02:10:00Z",
  "message": "Check 'Database Backup' is DOWN"
}

Notification Types

Down Alert

Sent when a check misses its expected ping time + grace period.

Recovery Alert

Sent when a previously down check receives a ping and is back up.

Slow Job Alert

Sent when a job's duration exceeds the configured maximum duration (maxDuration).

Status Pages

Create public status pages to share the health of your services with your team or customers.

Features

  • Uptime History — Visual timeline showing uptime for 7-90 days (depends on plan)
  • Real-time Status — Auto-updates every 30 seconds
  • Incidents — Post incidents and updates to keep users informed
  • Custom Branding — Add your logo, colors, and hide "Powered by CronOwl" (Pro plan)
  • Status Badge — Embed a status badge in your README or website

Creating a Status Page

  1. 1Go to Status Pages in your dashboard
  2. 2Click "New Status Page"
  3. 3Enter a title and description
  4. 4Select which checks to display
  5. 5Toggle "Public" to make it accessible

Status Badge

Embed a live status badge in your README or website:

Markdownmarkdown
[![Status](https://cronowl.com/api/status/YOUR_SLUG/badge)(https://cronowl.com/status/YOUR_SLUG)
HTMLhtml
<a href="https://cronowl.com/status/YOUR_SLUG">
  <img src="https://cronowl.com/api/status/YOUR_SLUG/badge" alt="Status">
</a>

Incident Management

Keep your users informed during outages by creating and managing incidents on your status pages.

Incident Workflow

InvestigatingIdentifiedMonitoringResolved

Update the incident status as you progress through the investigation and resolution.

Severity Levels

MinorSmall issues with minimal impact
MajorSignificant degradation affecting some users
CriticalComplete outage or major functionality broken

Integration Examples

Bash / Shell Script

backup.shbash
#!/bin/bash
set -e

# Signal job start (optional)
curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?start=1"

START_TIME=$(date +%s%3N)

# Your backup logic here
pg_dump mydb > /backups/mydb_$(date +%Y%m%d).sql
gzip /backups/mydb_$(date +%Y%m%d).sql

END_TIME=$(date +%s%3N)
DURATION=$((END_TIME - START_TIME))

# Signal completion with duration
curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?duration=$DURATION&exit_code=$?"

Crontab

crontab -ebash
# Run backup every day at 2am and ping CronOwl
0 2 * * * /path/to/backup.sh && curl -fsS https://cronowl.com/api/ping/YOUR_SLUG

# Alternatively, ping even on failure to track exit code
0 2 * * * /path/to/backup.sh; curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?exit_code=$?"

Python

job.pypython
import requests
import time

CRONOWL_URL = "https://cronowl.com/api/ping/YOUR_SLUG"

def main():
    # Signal start
    requests.get(f"{CRONOWL_URL}?start=1", timeout=10)

    start_time = time.time()

    try:
        # Your job logic here
        process_data()

        duration_ms = int((time.time() - start_time) * 1000)
        requests.get(f"{CRONOWL_URL}?duration={duration_ms}", timeout=10)

    except Exception as e:
        requests.get(f"{CRONOWL_URL}?status=failure&output={str(e)[:1000]}", timeout=10)
        raise

if __name__ == "__main__":
    main()

Node.js

job.jsjavascript
const CRONOWL_URL = 'https://cronowl.com/api/ping/YOUR_SLUG';

async function runJob() {
  // Signal start
  await fetch(`${CRONOWL_URL}?start=1`);

  const startTime = Date.now();

  try {
    // Your job logic here
    await processData();

    const duration = Date.now() - startTime;
    await fetch(`${CRONOWL_URL}?duration=${duration}`);

  } catch (error) {
    await fetch(`${CRONOWL_URL}?status=failure&output=${encodeURIComponent(error.message)}`);
    throw error;
  }
}

runJob();

Docker / Kubernetes CronJob

cronjob.yamlyaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: your-backup-image
            command:
            - /bin/sh
            - -c
            - |
              curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?start=1"
              START=$(date +%s%3N)
              /backup.sh
              EXIT_CODE=$?
              END=$(date +%s%3N)
              DURATION=$((END - START))
              curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?duration=$DURATION&exit_code=$EXIT_CODE"
          restartPolicy: OnFailure

GitHub Actions

.github/workflows/scheduled.ymlyaml
name: Scheduled Job
on:
  schedule:
    - cron: '0 */6 * * *'  # Every 6 hours

jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Signal start
        run: curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?start=1"

      - name: Run job
        id: job
        run: |
          START=$(date +%s%3N)
          # Your job here
          npm run process-data
          echo "duration=$(($(date +%s%3N) - START))" >> $GITHUB_OUTPUT

      - name: Signal completion
        if: always()
        run: |
          curl -fsS "https://cronowl.com/api/ping/YOUR_SLUG?duration=${{ steps.job.outputs.duration }}"

Ping Options

The ping endpoint accepts optional parameters to provide more context about your job.

ParameterDescriptionExample
start=1Signal job start (doesn't change status)?start=1
durationJob duration in milliseconds?duration=45000
exit_codeExit code (0 = success, non-zero = failure)?exit_code=0
status"success" or "failure"?status=failure
outputJob output/logs (max 1-10KB based on plan)?output=Done

Tip: Use exit_code to automatically mark jobs as failed when they exit with an error. CronOwl treats exit_code != 0 as a failure.

Slow Job Detection: If you set maxDuration on your check and send durationwith your ping, CronOwl will alert you when jobs take longer than expected.

Plans & Limits

FeatureFreeStarter ($8/mo)Pro ($19/mo)
Checks5100500
HTTP Monitors11050
Status Pages15
History Days33090
API Requests/min120300
Push & Telegram
Webhooks per Check310
Team Members5
Custom Branding

Frequently Asked Questions

What happens if my job runs but fails to ping CronOwl?

If CronOwl doesn't receive a ping within the expected time + grace period, it marks the check as "down" and sends alerts. This could mean your job failed, the network was unreachable, or the ping command wasn't executed.

How often does CronOwl check for missed pings?

CronOwl runs a status check every minute. This means you'll be alerted within 1 minute of your grace period expiring.

Can I pause monitoring temporarily?

Yes! Click the pause button on any check in your dashboard. Paused checks won't trigger alerts even if they miss pings. Resume monitoring anytime with a single click.

What's the difference between exit_code and status?

exit_code is the numeric exit code from your script (0 = success, non-zero = failure).status is a string ("success" or "failure") for explicit control. If both are provided, status takes precedence.

Is there a way to monitor from the command line?

Yes! CronOwl provides a full REST API. Use your API key to list checks, create new ones, view history, and more. See the API documentation for details.

How secure is my data?

CronOwl uses industry-standard security practices: HTTPS everywhere, encrypted data at rest, API keys are hashed before storage, and webhook URLs are validated to prevent SSRF attacks.