How to Write a Cron Expression for Every 5 Minutes
A cron expression for every 5 minutes is */5 * * * * — the */5 in the minute field means 'every 5th minute,' and the four asterisks leave hours, days, and months unrestricted. The job runs at :00, :05, :10, :15, and so on, every hour of every day. Build and sanity-check schedules without memorizing the syntax using ToolNest's free cron expression generator.
The expression, piece by piece
Standard cron has five fields, read left to right: minute hour day-of-month month day-of-week. In */5 * * * *, the minute field carries */5 — the step operator / applied to the full range *, meaning 'start at 0, then every 5th minute.' The remaining four asterisks mean 'every hour, every day of the month, every month, every day of the week' — no further restriction. So the schedule fires at 00:00, 00:05, 00:10 … 23:55, twelve times an hour, 288 times a day. The classic five-minute use cases: health checks that ping an endpoint, cache warmers, queue workers that drain a backlog, metric collectors, and backup jobs where hourly is too coarse and every minute is too chatty. If you only need it during business hours, restrict the hour field instead: */5 9-17 * * * runs every five minutes from 9:00 to 17:55 on all days.
The five fields, explained once
Each field accepts numbers, ranges, lists, and steps — memorizing the ranges is the whole game. Minute: 0–59. Hour: 0–23 (24-hour clock; 14 is 2 PM, and 2 AM is 2, not '2 AM'). Day of month: 1–31. Month: 1–12 (names like JAN also work in most implementations). Day of week: 0–7, where both 0 and 7 mean Sunday — a classic trap for anyone who assumes 1–7. Operators: * (every value), , (list: 1,15), - (range: 9-17), / (step: */5 or 0-30/10). You can combine them: 5,20,35,50 runs at four specific minutes, while 10-50/10 runs at :10, :20, :30, :40, :50. Everything left of what you restrict stays a wildcard, so adding one field narrows the schedule and nothing else.
Variations: offsets, weekdays, and business hours
*/5 always anchors at minute 0 — but sometimes you want the phase shifted. 2-59/5 * * * * runs at :02, :07, :12 … :57, useful for staggering two jobs so they never collide at :00. For weekday-only polling: */5 * * * 1-5 (Monday–Friday). For every five minutes during the workday: */5 8-18 * * 1-5. A common request is 'every 5 minutes but not at night' — cron has no negation, so you express the positive: */5 7-22 * * * covers 7 AM to 10:55 PM. Another frequent variant: every 5 minutes on the 1st of the month only — */5 * 1 * *. Note the day-of-month/day-of-week interaction below before combining those two fields; it bites almost everyone once.
Four mistakes that break schedules
1. Day-of-month AND day-of-week means OR. In standard cron, */5 * 1 * 1 runs when it's the 1st of the month or a Monday — not only on Mondays that are the 1st. If you need the intersection, encode it in the script, not the schedule. 2. Environment amnesia. Cron runs with a minimal environment: your PATH, virtualenv, and shell aliases from interactive login don't exist. Jobs that work in your terminal fail at 3 AM because `python` isn't found — use absolute paths (/usr/bin/python3) and set needed variables at the top of the crontab. 3. The % trap. In a crontab entry, an unescaped % becomes a newline and everything after it is fed to the command's stdin — date +%Y-%m-%d in a crontab silently breaks; escape it as +\%Y-\%m-\%d. 4. No overlap protection. If a 5-minute job occasionally runs 8 minutes, cron happily starts a second copy — implement a lock file (flock) or make the job idempotent, otherwise you get pile-ups that look like mysterious duplicates. 5. Assuming 'every 5 minutes' means evenly spaced. It doesn't during clock changes: on the spring-forward DST transition, the 2:00–3:00 hour vanishes, so you get 11 runs that hour instead of 12; on fall-back, one hour repeats. Systems that need exact spacing should schedule in UTC (* * * * * evaluated against UTC) and convert only for display — the same UTC discipline that makes Unix timestamps reliable in the first place.
Reading a cron expression backwards
When you inherit someone else's crontab, read it right to left: the rightmost fields are the broadest filters. In */5 9-17 * * 1-5, start at the end — '1-5' restricts to weekdays, then month and day-of-month are unrestricted, '9-17' narrows to business hours, and '*/5' sets the minute cadence. This backwards reading also reveals dead fields: a * in day-of-month alongside a restricted day-of-week means the day-of-week restriction is doing all the work. Two more reading skills worth building. First, spot the difference between 0/5 and */5: in most implementations they're identical (start at 0, step 5), but some parsers treat a bare 0/5 as starting at minute 0 explicitly — know your implementation. Second, translate ranges into run counts to sanity-check load: */5 is 288 runs/day, */5 9-17 * * 1-5 is 108 runs per weekday, and 2-59/5 * * * * is still 288 — the offset changes when, never how many. If a schedule's run count surprises you, re-read the fields before you deploy.
Beyond classic cron: Quartz, GitHub Actions, systemd
Not every scheduler speaks the same dialect, and the field count is the giveaway. Quartz (Java) uses six fields with seconds first: 0 0/5 * * * ? means every 5 minutes — note the ? placeholder, Quartz's 'no specific value' for the day fields. GitHub Actions scheduled workflows use five fields like classic cron (* /5 * * * *) but run in UTC and, on the free tier, the shortest reliable interval is 5 minutes — with the caveat that high-load periods can delay runs. systemd timers don't use cron syntax at all: OnCalendar=*:0/5 expresses 'every 5 minutes.' Node's node-cron optionally supports a sixth seconds field. The practical rule: when you move a schedule between systems, re-derive the expression in the target dialect rather than pasting — field-order mistakes are silent, and 'silent' in scheduling means 'didn't run and nobody noticed for a week.'
Test before you trust it
A schedule you haven't verified is a hope, not a plan. First, read the expression back in plain English — ToolNest's cron expression generator shows the next several run times, which catches field-order mistakes instantly. Second, point the job at a harmless action first: append a timestamp to a log file for an hour and confirm twelve entries appear. Third, log every real run with its exit code — cron emails output to the crontab owner by default, but only if the system can deliver mail; redirect to a file (>> /var/log/myjob.log 2>&1) so failures leave evidence. Fourth, monitor from outside: a dead-man's-switch service that alerts when the expected 5-minute heartbeat stops is the difference between a 10-minute outage and discovering Monday's gap on Friday. Schedules pair naturally with data pipelines — our guide on converting CSV to JSON ends with exactly this pattern: a cron job that turns a nightly spreadsheet export into API-ready JSON. And if your five-minute job refreshes API credentials, our JWT guide shows how to inspect the tokens it's minting, while what JSON is covers the payload format those jobs usually shuffle around.
Do it in one click
Build cron expressions visually and preview the next run times — free, no signup.
Open the Free Tool →