R4.02.1 · dive 1
Cron vs interval
Two ways to name "when next": a cron expression names a wall-clock calendar slot, a fixed interval names a gap. Both reduce to one millisecond — the registry's score.
A cron expression like 0 9 * * * matches a calendar position —
09:00 every day — and the next run is the next slot at or after now. An interval like
every: 900000 ms names a gap and the next run is the previous run plus the gap. Compute
the next run each way over a fixed clock on the right, and read the two next-run timestamps.
Next run from a fixed now · cron 0 9 * * * vs interval every 15 min
The cron expression — a wall-clock slot
A cron expression is five fields — minute, hour, day-of-month, month, day-of-week.
0 9 * * * reads "minute 0, hour 9, any day, any month, any weekday" — 09:00 every
day. The next run is the earliest calendar slot at or after the current time that the expression matches.
Cron anchors to the wall clock, so a daily-at-09:00 schedule fires at 09:00 regardless of when it last ran or how long the last run took. Move now across 09:00 in the figure and the cron next-run snaps to today's 09:00 while now is before it, then to the next day's 09:00 once now has passed it.
A cron expression names a calendar slot; the next run is the earliest matching slot at or after now, anchored to the wall clock.
The fixed interval — a gap
A fixed interval is a single number of milliseconds — every: 900000 is fifteen
minutes. The next run is the previous run plus the gap. An interval anchors to its own previous run rather than
to the calendar, so an interval-every-15-min schedule fires at :00, :15, :30, :45 past whatever minute it
started on, marching forward by the gap.
Switch the cadence to the interval in the figure: the next-run marks step every fifteen minutes, and the next run is the first mark at or after now — not a calendar position, but the next gap boundary.
A fixed interval names a gap; the next run is the previous run plus the gap, anchored to the prior run rather than the calendar.
Both reduce to one timestamp
The two rules compute differently but produce the same kind of value: a future millisecond. That single number
is the score ZADD'd into the registry against the scheduler's member. The registry does
not record whether the next run came from a calendar match or a gap addition — it stores a sorted set of
next-run times and pops the earliest.
Naming the cadence is the only place the two rules differ; downstream, a cron schedule and an interval schedule are the same one-entry-scored-by-next-run row. The score is the meaning; the cadence is the rule that produced it.
- cron
0 9 * * *— a calendar slot; next run = the earliest matching slot at or after now.- interval
every: 900000— a gap; next run = previous run + gap.- score
- The computed next-run millisecond, written with
ZADDto the:repeatregistry — the same shape for both rules.
Same registry row · either rule produces one ZADD with one next-run score
Cron and interval are two rules with one output: a future millisecond, stored as the registry's score; downstream the two schedules are identical rows, differing only in the cadence field on the options hash.
In EchoMQ — pattern and every on the options hash
The store function storeRepeatableJob(repeatKey, customKey, nextMillis, rawOpts) in
addRepeatableJob-2.lua is given nextMillis already computed by
the caller, and it records two things: the next-run time on the registry sorted set, and the cadence on the
companion hash.
-- addRepeatableJob-2.lua · storeRepeatableJob (real) ZADD repeatKey nextMillis customKey -- the next run, on the registry ZSET HMSET repeatKey..":"..customKey -- the cadence, on a separate hash "name" opts.name "pattern" opts.pattern "every" opts.every
The pattern field holds the cron expression; the every field
holds the interval. EchoMQ stores both so a schedule can be defined either way; only one is set per scheduler.
The registry sorted set carries only the computed nextMillis; the rule that produced it
lives in the companion hash, alongside an optional tz.
A scheduler needs a rule for "when next." Cron names a calendar slot; an interval names a gap. Both reduce to one future millisecond — the score the registry stores, identical in shape for either rule.
storeRepeatableJob writes the computed nextMillis to the
:repeat ZSET with ZADD and the cadence fields
(pattern, every, tz) to a companion
HMSET hash — the rule on the hash, the next run on the registry.
The pattern says cron and interval are two rules with one timestamp output; in EchoMQ the rule lives
on the companion HMSET hash and the computed next run on the :repeat
ZSET.
pattern plus tz resolves a
calendar slot across daylight-saving transitions, and how a missed slot is reconciled — belongs to the
scheduler subsystem the dedicated EchoMQ course covers at
E6 · Lifecycle controls. This dive teaches the two cadence shapes and the
single timestamp they both become; that course teaches the parser that computes it.
References
The cron expression as a calendar cadence, the command that writes the computed next run, the sorted set both cadences feed, and the queue protocol whose cadence options EchoMQ ports.
Sources
- Wikipedia — Cron — the five-field cron expression as a calendar cadence spec.
- Redis — ZADD — the command that writes the computed next-run millisecond as the registry score.
- Redis — Sorted sets — the registry of next-run times both cadences feed.
- BullMQ — the queue protocol — the repeatable-jobs cadence options (
pattern,every,tz) EchoMQ ports.
Related in this course
- R4.02 · Schedulers & repeatable jobs — the module hub.
- R4.02.2 · The upsert, no duplicates — storing the computed next-run without duplicating.
- R4.02.3 · Start-to-start cadence — producing the next run from the cadence.
- R4 · Score as meaning — the
:repeatZSET in the orientation arc. - E6 · Lifecycle controls — the EchoMQ course: cron parsing, timezones, and the scheduler subsystem.