Cron expression for Every 8 hours
0 */8 * * *
Runs once every 8 hours, starting at midnight.
Next 5 runs (your local time)
These are shown in your browser’s timezone. The job itself runs in the scheduler’s timezone — often UTC — so the real run time can differ.
What people actually schedule with 0 */8 * * *
- Three-shifts-a-day reporting that aligns with morning/afternoon/overnight operations teams
- A token refresh or session-cleanup job for credentials that expire on roughly an 8-hour window
- Moderate-cost data warehouse loads where three passes a day keep BI dashboards current without nightly-only staleness
Use 0 */8 * * * on your platform
It’s the same 5-field expression everywhere — what changes is where you put it and which timezone it runs in.
Linux / crontab
0 */8 * * * /path/to/your-command
Runs in the server’s local timezone — check it with timedatectl.
Full field reference: crontab(5) man page.
GitHub Actions
on:
schedule:
- cron: "0 */8 * * *"
GitHub Actions always runs scheduled jobs in UTC — there is no timezone setting, and runs can be delayed under load (official docs).
Kubernetes CronJob
spec:
schedule: "0 */8 * * *"
Defaults to UTC. Set spec.timeZone (Kubernetes 1.27+)
for a specific zone — see the
CronJob docs.
Quartz / Spring @Scheduled
Quartz uses 6 fields (seconds first): 0 0 */8 * * *. Watch out:
Quartz day-of-week is 1=SUN … 7=SAT (not 0–6), and day-of-month /
day-of-week use ? — double-check if your schedule touches those fields
(Quartz cron reference).
Gotchas with every 8 hours schedules
0 */8 * * *fires at 00,08,16 — three times, and the wrap is clean because 24÷8=3. The subtle trap: it does NOT give you an 8-hour gap on the third interval relative to the next day's first unless you remember 16:00→00:00 is exactly 8 hours. People expecting 00,08,16,24 get confused when 24 is just the next 00.- Three runs a day amplifies timezone misalignment. If you picked 8-hour spacing to match human shifts but cron runs UTC, the 00/08/16 UTC fires won't land on your local shift changes — set
CRON_TZ=America/Vancouver(or wrap the command withTZ=) so the runs actually hit shift boundaries, then re-check after every DST flip. - DST quietly turns one day into a 7- or 9-hour gap. On switch days, the fixed 00/08/16 wall-clock times mean one interval gains or loses an hour; if downstream logic assumes 'exactly 8 hours of data per run', that day's window will be off by 60 minutes — drive the window from row timestamps, not 'now minus 8 hours'.
Will you know if this job silently fails?
Cron jobs fail quietly — a server reboots, a path changes, or an error code is ignored — and nobody notices until the data is missing. A cron monitor (a dead-man’s-switch) alerts you when a scheduled job does not check in on time.
Monitor your cron jobs with UptimeRobot →
Disclosure: this is an affiliate link — we may earn a commission if you sign up, at no extra cost to you.
Is 0 */8 * * * the right schedule?
If three passes a day is more than you need, every 12 hours gives a clean twice-daily rhythm; if you want denser coverage, every 6 hours steps up to four evenly-spaced runs.
Or use the interactive cron generator & explainer, read the complete cron syntax guide, or pick another common schedule: