← Blog  ·  October 2026

What Is a Cron Job? A Complete Beginner's Guide

Scheduled tasks, cron syntax, real-world examples, and the one thing cron doesn't do for you.

If you've spent any time working with Linux servers, CI/CD pipelines, or web applications, you've probably encountered the word "cron." Maybe you've seen a crontab file on a server, a GitHub Actions workflow with on: schedule:, or a CronJob in a Kubernetes manifest. They all trace back to the same concept: a scheduled task that runs automatically at defined time intervals, without anyone pressing a button.

This guide explains what cron is, how it works, how to read cron syntax, and where you'll encounter cron in real-world systems.


What is a cron job?

A cron job is a scheduled task that runs automatically on Unix and Linux systems at a specified time or interval. The name comes from Chronos (χρόνος), the Greek word for time.

Cron jobs are used for any work that needs to happen on a schedule rather than on demand:

The key property: cron jobs run in the background, unattended, without any user interaction. Once scheduled, they run reliably — until they don't (more on that later).


How cron works

On a Linux server, cron is managed by a background process called crond (the cron daemon). It runs continuously, waking up every minute to check whether any scheduled jobs need to run. When the current time matches a job's schedule, crond executes the associated command.

Jobs are defined in crontab files (cron table). Each user on a system can have their own crontab, and there's a system-wide crontab at /etc/crontab.

Basic crontab commands

# List your current cron jobs
crontab -l

# Open your crontab in an editor
crontab -e

# Remove your entire crontab (careful!)
crontab -r

When you run crontab -e, you'll see a file where each line defines one scheduled job. Lines starting with # are comments. Every other line is a schedule definition followed by the command to run.


Cron syntax: the five fields

Every cron job is defined by five time fields followed by the command to execute:

┌───────────── minute (0–59)
│ ┌─────────── hour (0–23)
│ │ ┌───────── day of month (1–31)
│ │ │ ┌─────── month (1–12)
│ │ │ │ ┌───── day of week (0–7, both 0 and 7 = Sunday)
│ │ │ │ │
* * * * *  command-to-run
PositionFieldAllowed valuesSpecial values
1stMinute0–59*/15 = every 15 minutes
2ndHour0–230,12 = midnight and noon
3rdDay of month1–311,15 = 1st and 15th
4thMonth1–12*/3 = every quarter
5thDay of week0–7 (0 & 7 = Sun)1-5 = Mon–Fri

Special characters

Real-world examples

ExpressionMeaning
* * * * *Every minute
0 * * * *Every hour, on the hour
0 2 * * *Every day at 2:00am
0 9 * * 1-5Weekdays (Mon–Fri) at 9:00am
0 0 1 * *First day of every month at midnight
*/15 * * * *Every 15 minutes
30 3 * * 0Every Sunday at 3:30am
0 0 1 1 *January 1st at midnight (yearly)
0 9 * * 1Every Monday at 9:00am
*/30 9-17 * * 1-5Every 30 min during business hours, weekdays
🧮 Not sure if your expression is right? Test it free — paste any cron expression and see the plain-English description and next 5 run times →

Shorthand strings

Most cron implementations also accept human-readable shorthand:

ShorthandEquivalentMeaning
@yearly0 0 1 1 *Once a year, Jan 1st midnight
@monthly0 0 1 * *Once a month, 1st at midnight
@weekly0 0 * * 0Once a week, Sunday midnight
@daily0 0 * * *Once a day at midnight
@hourly0 * * * *Once an hour
@reboot—Once at system startup

A simple crontab example

# Back up the database every day at 2am
0 2 * * * /opt/scripts/backup.sh

# Send a weekly report every Monday at 9am
0 9 * * 1 /opt/scripts/weekly-report.py

# Clean up temp files every hour
0 * * * * find /tmp -name "*.tmp" -mtime +1 -delete

# Rotate logs every night at midnight
0 0 * * * /usr/sbin/logrotate /etc/logrotate.conf

Where cron appears in modern systems

Linux crontab is the original, but the same concept appears across almost every modern deployment platform. Once you understand cron syntax, you can use it everywhere.

GitHub Actions (on: schedule:)

on:
  schedule:
    - cron: '0 3 * * *'   # Run every day at 3am UTC

jobs:
  nightly-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

GitHub Actions scheduled workflows use standard cron syntax. One important caveat: GitHub silently disables scheduled workflows on repositories with no recent push activity (approximately 60 days). The workflow just stops running — no error, no notification.

AWS EventBridge (formerly CloudWatch Events)

# AWS cron expression — note: year field added, no seconds
cron(0 3 * * ? *)     # Every day at 3am UTC
cron(0 9 ? * MON *)   # Every Monday at 9am UTC

AWS uses a 6-field cron syntax that adds a year field and uses ? for "no specific value" in the day-of-month and day-of-week fields.

Kubernetes CronJobs

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: my-backup-image

Kubernetes uses standard 5-field cron syntax. CronJobs create a new Pod on schedule. Failed pods are visible in the cluster, but missed runs (e.g., the cluster was down during the scheduled window) are not automatically retried.

Heroku Scheduler

Heroku Scheduler uses a simplified UI (every 10 min / every hour / every day at X time) rather than raw cron syntax, but it's conceptually the same: a command that runs on a schedule in your application's environment.

Other platforms

Virtually every platform that runs application code has a scheduling primitive: Railway, Fly.io, Render, Vercel (via cron triggers), Laravel's task scheduler, Celery Beat, APScheduler, and the schedule Python library. All of them implement the cron concept, whether or not they use the exact cron syntax.


What cron doesn't do

Cron is good at one thing: running a command at a specified time. It doesn't do much else.

Specifically, cron does not:

The silent failure problem The most common cron war story: a nightly data sync stopped running on Thursday. The team found out Monday — from a user reporting stale data. Cron ran the job Thursday at 2am, the script failed silently, cron tried again Friday and it failed again, and the same Saturday and Sunday. Nobody got an alert. The server had no way to know anyone cared about the output.

This is why cron monitoring exists. The standard pattern is a dead man's switch: your job sends an HTTP ping at the end of each successful run. A monitoring service watches for that ping on the expected schedule. If the ping doesn't arrive — because the job failed, because the scheduler crashed, because the server went down — you get an alert.

Adding monitoring to a crontab entry is one extra line:

# Backup with monitoring — ping only fires if backup succeeds
0 2 * * * /opt/scripts/backup.sh && curl -fsS https://cronwatch.io/ping/YOUR-TOKEN

The && ensures the curl only runs if the script exits with code 0. If the script fails, no ping — and the monitoring service alerts you.

📟 Know the moment a cron job stops running

CronWatch monitors your scheduled jobs with a dead man's switch. Add one line to your cron job. If the ping stops arriving — because the job failed, stalled, or the scheduler itself crashed — you get an email alert. Works with crontab, GitHub Actions, AWS EventBridge, Kubernetes CronJobs, and Heroku Scheduler.

Join the CronWatch waitlist → Test your cron expression free

Quick reference

ConceptWhat it is
cronThe Unix scheduling system; runs jobs on a time-based schedule
crondThe background daemon that reads crontabs and runs scheduled commands
crontabThe file that defines scheduled jobs; one job per line
cron expressionThe 5-field time specification (* * * * *) that defines when a job runs
cron jobA scheduled command defined in a crontab
dead man's switchA monitoring pattern where the job signals success; alert fires if signal is absent

Further reading

← All articles  ·  CronWatch  ·  Cron parser tool