Cron expression for every 4 hours
The cron expression 0 */4 * * * runs a job every 4 hours, on the hour — at 00:00, 04:00, 08:00, 12:00, 16:00 and 20:00 every day, six times in 24 hours. The same syntax works in Linux crontab, Kubernetes CronJob and GitHub Actions. AWS EventBridge needs the 6-field form: cron(0 */4 * * ? *).
Quick reference
| Platform | Expression |
|---|---|
| Unix / Linux crontab | 0 */4 * * * |
| Kubernetes CronJob | 0 */4 * * * |
| GitHub Actions | 0 */4 * * * |
| AWS EventBridge Rules / Scheduler | cron(0 */4 * * ? *) |
| Quartz (Java) | 0 0 */4 ? * * |
What does “every 4 hours” actually mean?
The expression fires on the hour at 00:00, 04:00, 08:00, 12:00, 16:00 and 20:00. Six runs per 24 hours. The */4 in the hour field means “every 4 hours starting from 0”, and the leading 0 in the minute field pins the trigger to exactly the hour.
It does NOT mean “4 hours after the previous run finished”. If your job sometimes takes longer than 4 hours, the next run starts on schedule and overlaps — see Common mistakes below.
Compared to every 2 hours (0 */2 * * *), the 4-hour cadence cuts daily fires from 12 to 6 — useful for jobs with real per-run cost (full snapshots, expensive ETL, cross-region replication) where the extra coverage of every-2-hours isn’t worth the resource doubling. It’s also wide enough that overlapping runs are uncommon in practice, but still close enough that long-running jobs can cause stacking — set concurrency policies explicitly for jobs that occasionally exceed 90 minutes.
Variations
| Schedule | Expression |
|---|---|
| Every 4h, weekdays only | 0 */4 * * 1-5 |
| Every 4h, business hours (08–20) | 0 8,12,16,20 * * * |
| Every 4h, offset by 1 hour (01, 05, 09, 13, 17, 21) | 0 1-23/4 * * * |
| Every 4h, on the half hour past (:30) | 30 */4 * * * |
| Every 4h in AWS, weekdays only | cron(0 */4 ? * MON-FRI *) |
How do I use it on each platform?
Linux crontab:
0 */4 * * * /usr/local/bin/refresh-cache
Kubernetes CronJob:
apiVersion: batch/v1
kind: CronJob
metadata:
name: refresh-cache
spec:
schedule: "0 */4 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: refresh
image: my-org/cache-refresh:1.0
For 4-hour intervals on Kubernetes, concurrencyPolicy: Forbid is usually the right call — runs that take 4+ hours are common (data refreshes, ETL, full backups), and stacked pods can starve cluster resources.
AWS EventBridge (CLI):
aws events put-rule \
--name refresh-cache \
--schedule-expression "cron(0 */4 * * ? *)"
GitHub Actions:
on:
schedule:
- cron: '0 */4 * * *'
GitHub Actions runs in UTC, so a 0 */4 * * * schedule fires at 00:00, 04:00, 08:00 UTC. Translate to your team’s timezone if the wall-clock alignment matters — there is no per-workflow timezone option.
Common mistakes
Confusing */4 in the hour field with */4 in the minute field. */4 * * * * runs every 4 minutes — 360 times per day, two orders of magnitude more than intended. Always pin the minute to a single value (0) when stepping the hour field.
Stacking long-running jobs. A 4-hour interval is often used for jobs that are themselves several hours long. Without concurrencyPolicy: Forbid (Kubernetes) or a serialization layer (Lambda reserved concurrency 1, SQS FIFO queue), stacked runs compound resource pressure during a slow patch.
Forgetting AWS’s 6-field requirement. cron(0 */4 * * *) is rejected. AWS needs cron(0 */4 * * ? *) — ? for dow and trailing * for year.
Mixed-timezone containers. If your container’s TZ differs from the cluster default, 0 */4 fires at clock-aligned times in the container’s timezone, not the host’s. For environments with mixed TZs, set TZ=UTC explicitly in the CronJob spec or container image. The Kubernetes CronJob schedule generator emits a complete manifest with timeZone, concurrencyPolicy: Forbid and startingDeadlineSeconds already configured, and the AWS EventBridge cron generator handles the 6-field wrapper plus IaC snippets.
For ready-to-paste expressions for other intervals, see common cron schedules, or build a custom expression with the Cron Expression Builder.
Frequently asked questions
- Does `0 */4 * * *` start at midnight or at the next 4-hour mark?
- `*/4` aligns to clock hours starting from `0`, so the schedule fires at exactly 00:00, 04:00, 08:00, 12:00, 16:00 and 20:00 — six times per day. There is no drift relative to wall-clock time, regardless of when the cron daemon started.
- How do I run every 4 hours but offset by 1 hour (01:00, 05:00, 09:00…)?
- Use `0 1-23/4 * * *` — fires at hour 1, then every 4 hours from there: 01:00, 05:00, 09:00, 13:00, 17:00, 21:00. Or list explicitly: `0 1,5,9,13,17,21 * * *`.
- Why use a cron expression instead of `rate(4 hours)` in AWS EventBridge?
- `rate(4 hours)` fires every 4 hours from when the rule was created, so a rule created at 03:17 fires at 07:17, 11:17, 15:17 etc. — the actual minute drifts with the creation timestamp. `cron(0 */4 * * ? *)` always fires at clock-aligned times. Use `cron` when you care about wall-clock alignment; `rate` when you don't.
Need a different schedule?
Build cron expressions for Unix, Kubernetes, AWS EventBridge and Quartz — with a human-readable description and the next 5 run times.
Open the Cron Expression Builder →Related
What is a cron job?
A cron job is a scheduled command that runs at fixed times on Unix-like systems. The schedule is a one-line cron expression of five space-separated fields.
Cron expression for every 5 minutes
The cron expression `*/5 * * * *` runs every 5 minutes in Linux crontab, Kubernetes, GitHub Actions; `cron(*/5 * * * ? *)` in AWS EventBridge.
Cron expression for every 15 minutes
The cron expression `*/15 * * * *` runs every 15 minutes — at :00, :15, :30, :45 — across Linux, Kubernetes, GitHub Actions and AWS.
Cron expression for every 30 minutes
The cron expression `*/30 * * * *` runs every 30 minutes — at :00 and :30 of every hour. Same in Linux, Kubernetes and GitHub Actions; `cron(*/30 * * * ? *)` in AWS.
Cron expression for every hour
The cron expression `0 * * * *` runs once per hour on the hour. Same syntax in Linux, Kubernetes and GitHub Actions; `cron(0 * * * ? *)` in AWS EventBridge.
Cron expression for daily at midnight
The cron expression `0 0 * * *` runs once daily at midnight. Watch the timezone — Kubernetes < 1.25 and AWS EventBridge default to UTC, not local time.