Every Day at 4 AM Cron Expression
Runs once daily at 04:00 server time.
0 4 * * * in POSIX cron
Expression
0 4 * * *Try it in the tester →Field Breakdown
How It Works
Fires at 04:00 every day — useful when 03:00 is already saturated with backup jobs and you need a slightly later slot.
Example Run Times
- Mon 04:00:00
- Tue 04:00:00
- Wed 04:00:00
- Thu 04:00:00
- Fri 04:00:00
Frequently Asked Questions
Does this conflict with logrotate defaults?
Debian's default logrotate runs at 06:25 via `/etc/cron.daily`, so a 04:00 job will complete before logrotate kicks in.
0 4 * * * in Quartz / Spring
A single firing per day at 04:00:00 — the hour field carries the 4, while seconds and minutes are zeroed. Teams reach for 4 AM when the 3 AM block is already crowded with backups and they want a clean lane of their own.
Quartz / Spring expression
0 0 4 * * ?Try it in the tester →At 04:00:00
Unix / POSIX equivalent: 0 4 * * *
Field Breakdown
Using It with Quartz / Spring
In a Spring Boot service this becomes @Scheduled(cron = "0 0 4 * * ?") on a bean method; standalone Quartz wraps the same string in CronScheduleBuilder.cronSchedule() when building the CronTrigger. The 4 AM slot typically hosts second-wave maintenance: jobs that consume the output of an earlier backup or export, retention sweeps, and report pre-computation that should be done before anyone is awake to notice. If the job genuinely depends on a 3 AM predecessor finishing, an hour of slack is a guess, not a guarantee — Quartz's JobChainingJobListener (or triggering the follow-up from the first job's completion) expresses the dependency directly.
Quartz-Specific Notes
- →DST transitions in most timezones happen between 01:00 and 03:00 local time, so a 04:00 trigger usually sails through both changeover nights untouched.
- →Quartz evaluates the 4 against the trigger's TimeZone, falling back to the JVM default — in a container shipped with TZ=UTC, this fires at 04:00 UTC, not 4 AM where your team sleeps.
- →One firing per day means a failed run leaves a 24-hour hole; emit a success metric from the job and alert on its absence rather than trusting the schedule.
Frequently Asked Questions
My backup runs at 3 AM — is scheduling the dependent job at 4 AM safe?
Only as long as the backup never exceeds an hour. Time-gap sequencing breaks silently the night the backup runs long; chaining the second job off the first one's completion (a JobListener in Quartz, or invoking it at the end of the first method in Spring) removes the race entirely.
How do I move this to 4:30 AM?
Set the minute field: 0 30 4 * * ?. The leading 0 stays as the seconds field.
0 4 * * * in AWS EventBridge
A single daily trigger at 04:00 UTC, one notch past the 03:00 slot where nightly backup chains traditionally pile up. Teams reach for this hour when a job must run after the rest of the overnight batch fleet has gone quiet but still finish well before any business day begins.
AWS EventBridge expression
cron(0 4 * * ? *)Try it in the tester →At 04:00 UTC
Unix / POSIX equivalent: 0 4 * * *
Field Breakdown
Using It with AWS EventBridge
Create it as a scheduled rule in the EventBridge console or declare it in a SAM template as a ScheduleV2 event on the function that does the work. The 4 AM slot tends to host second-wave maintenance: verifying that the 03:00 snapshot completed and alerting if it did not, vacuuming and analyzing Postgres tables on RDS once backup I/O has subsided, or compacting the night's accumulated S3 objects. Since the job owns a quiet hour, it can afford longer Lambda timeouts or a chunky Fargate task without competing for capacity with your own earlier jobs.
AWS-Specific Notes
- →04:00 UTC is exactly midnight in US Eastern during daylight saving but 23:00 the previous evening in winter — a report stamped with the local date can flip between two calendar days across the DST change.
- →In Tokyo this fires at a constant 13:00 JST, mid-business-day, because Japan observes no daylight saving.
- →With one invocation per day, a single failure means a 24-hour data gap — attach a dead-letter queue to the target and alarm on its depth.
Frequently Asked Questions
How do I make this run at 4 AM in my own timezone instead of UTC?
Classic EventBridge rules only evaluate UTC. Move it to EventBridge Scheduler — in the console that's Scheduler > Create schedule, or a CreateSchedule API call with the identical cron body plus ScheduleExpressionTimezone — and DST handling comes along for free.
My 3 AM backup sometimes overruns — can the 4 AM job wait for it?
Not via cron; clock-chained jobs race whenever the first one is slow. Either have the backup emit a completion event that a second EventBridge rule matches, or put both steps in one Step Functions state machine so ordering is explicit.
0 4 * * * in GitHub Actions
A daily run at 04:00 UTC — 365 fire times a year (366 in leap years), four hours after the UTC date rolls over. For US East Coast teams this slot has a hidden bonus: during daylight saving, 04:00 UTC is exactly midnight Eastern, making it a natural local-midnight nightly without touching the hour field.
GitHub Actions expression
0 4 * * *Try it in the tester →At 04:00 UTC
Unix / POSIX equivalent: 0 4 * * *
Field Breakdown
Using It with GitHub Actions
In workflow YAML it reads on: schedule: - cron: "0 4 * * *", quoted as always. The 4am-UTC slot suits second-wave nightly work — jobs that consume what midnight-UTC pipelines produce, such as uploading the database snapshot a separate system finished writing, rebuilding nightly Docker images from freshly published bases, or rerunning an E2E suite against the artifacts of an upstream nightly build. If the ordering dependency is hard rather than approximate, chain with workflow_run on the upstream workflow's completion instead of trusting a four-hour gap.
GitHub-Specific Notes
- →04:00 UTC is 00:00 US Eastern while daylight saving is in effect and 23:00 the previous evening once clocks fall back — the cron line never moves, only its local meaning does.
- →The asterisks in the day fields mean this includes Saturdays and Sundays; trim to 0 4 * * 1-5 if weekend runs are wasted effort.
- →Only the copy of the workflow file on the default branch produces scheduled runs — a 4am schedule sitting in an open pull request fires nothing.
Frequently Asked Questions
How do I schedule a workflow for 4am in my own timezone instead of UTC?
Convert manually — there is no timezone option for the schedule event. For US Eastern, 4am local is 0 8 * * * under daylight saving and 0 9 * * * in winter, and the file needs editing at each transition if the local hour must hold exactly.
Will the run land at 04:00 sharp?
Treat 04:00 as the earliest possible start, not a guarantee — GitHub queues scheduled runs and actual start times commonly trail the nominal slot by a few minutes.
Can I make this 4am job wait for my midnight workflow to finish first?
Not via cron — schedules are independent. Use the workflow_run trigger on the midnight workflow's completion instead, which removes the guesswork about whether four hours was enough headroom.