AI Automation

How Do You Schedule Automations So They Do Not Collide?

Written by
Pravin Kumar
Published on
Sep 25, 2026

How do you schedule automations so they do not collide?

Spread them across the hour, give each one a guard against overlapping with itself, and make anything that depends on another job wait for it rather than guess. Most scheduling problems come from jobs that were each written sensibly in isolation and never looked at together.

Collisions are the quietest class of automation failure. Nothing errors, nothing alerts, and the results are just slightly wrong in ways that take weeks to notice. A report built from data that was still being written. A record updated twice with different values. A sync that skipped a row because another job had it locked.

The fix is almost entirely bookkeeping rather than engineering, which is why it gets deferred. Nobody gets credit for a schedule that stops producing problems nobody could see.

What does a collision actually look like?

Three shapes. Two jobs writing to the same record in the same minute, so the later write silently wins. One job reading while another is midway through updating, so the read catches a half-finished state. And a job still running when its next scheduled instance starts, so two copies run at once.

The third one is the most common and the least suspected. A nightly sync that used to take four minutes now takes twelve because the dataset grew, and it is scheduled every ten minutes. Nobody changed anything. The data simply crossed a line and the job started overlapping itself.

What makes all three hard to spot is that the symptom appears somewhere else. The complaint is that a number in a dashboard looks wrong, and the cause is two jobs that happened to run together on Tuesday. Tracing backwards from symptom to schedule is the hard part, and it is much easier if you designed the schedule deliberately in the first place.

Why does everything end up running at the top of the hour?

Because that is the default, and because humans like round numbers. Every builder picks hourly, or nine in the morning, or midnight, and after two years you have eleven jobs that all start at exactly the same instant and then contend for the same APIs and the same records.

The platforms encourage it. Presets offer every hour, daily, weekly, and the natural reading of every hour is on the hour. Nobody deliberately chooses seventeen minutes past. Yet seventeen minutes past is almost always a better choice, for no reason other than that nothing else is there.

The same clustering happens in the opposite direction with external services. The top of the hour is when everybody else's jobs run too, so that is when third-party APIs are slowest and rate limits are tightest. Moving off the hour buys you a quieter road as well as a quieter house.

How do you find the collisions you already have?

Make a list of every scheduled job, its time, its expected duration, and what it writes to. One table, one row per job. It sounds tedious and it takes about an hour, and it will show you two or three overlaps that nobody knew about.

Sort that table by time and read down the column. Anything sharing a start time is a candidate. Then sort it by what each job writes to, and look for two jobs touching the same object anywhere near each other. Those two sorts catch nearly everything.

The duration column is the one people leave blank, and it is the one that matters most. If you do not know how long a job actually takes, you cannot know whether it finishes before the next thing starts. Look at the run history and take the slowest recent run rather than the typical one, because the slowest run is the one that causes the incident.

What is the right way to space things out?

Give each job its own minute and leave a gap larger than its worst observed duration before anything that depends on it. If a job takes up to twelve minutes, the thing that reads its output should not start fifteen minutes later. It should start when the first job says it is done.

For independent jobs, spreading is enough. Put one at seven minutes past, one at nineteen, one at thirty-four. The specific numbers do not matter, only that they are not the same and not neat. I tend to use minutes that look arbitrary precisely so that nobody later assumes they can round them.

Record the reasoning next to the schedule. A minute value with no explanation will eventually be changed by somebody tidying up, and the collision returns. This is the same argument as naming, and for the same reason: the explanation has to live where the thing lives. I made that case in the piece on naming conventions.

When should one automation trigger the next instead?

Whenever the second one genuinely needs the first to have finished. A schedule is a guess about duration. A trigger is a fact about completion. If the relationship is a dependency, express it as a dependency rather than as two times that currently happen to be far enough apart.

The reason people use timing instead is that chaining is slightly more work to set up and much more annoying to debug when the chain breaks. That is a real trade-off. My rule is that anything where a wrong result would be believed rather than noticed gets chained, and everything else can be scheduled with a generous gap.

Be careful not to chain too far. A chain of six jobs is a single fragile pipeline where any one failure stops everything downstream, and the failure appears as silence rather than as an error. Two or three links is usually the limit before you want a reconciliation check at the end instead, which I went through in the piece on a daily reconciliation check.

What do you do about jobs that overrun?

Stop the next instance from starting. Most platforms have some form of concurrency control, and where they do not, you can do it yourself with a simple flag: the job sets a marker when it starts and clears it when it ends, and refuses to run if the marker is already set.

The flag approach needs one safeguard, which is a timeout. If a job crashes between setting the marker and clearing it, the marker stays set forever and the automation silently stops running. Include the start time in the marker and ignore markers older than some sensible age, so a crash costs you one cycle rather than everything after it.

Then alert on the skip. A job that declined to run because the previous instance was still going is telling you something important about growth, and if that skip is silent you will only find out when the backlog becomes visible to a customer. One notification per skipped run is the right volume, and it should go to a named person rather than to a channel.

How do time zones make this worse?

They move your carefully spaced jobs twice a year without asking. A schedule written in a zone that observes daylight saving shifts by an hour relative to a schedule written in a zone that does not, and two jobs that were an hour apart suddenly start together.

The defensive move is to define every schedule in one zone and convert for humans, rather than letting each job carry the zone of whoever built it. Working across Bengaluru and client teams in other countries, I have watched more than one overnight process quietly move into the middle of somebody's working day because nobody wrote down which clock the schedule was on.

Also think about what your jobs should do at the edges of a day rather than only when they run. A daily job that runs at midnight in one zone is processing yesterday in another, and any date arithmetic inside it needs to know which. That question extends to the calendar as a whole, which is why I wrote about what an automation should do on a public holiday.

What changes when volume grows?

The gaps you chose stop being generous. Every schedule contains an implicit assumption about how long things take, and that assumption ages badly as data accumulates. The system that was comfortable at a thousand records is not comfortable at fifty thousand, and nothing warns you on the way.

So put a review in the calendar rather than waiting for a symptom. Once a quarter, look at the longest recent run of every scheduled job and compare it to the gap you left. Ten minutes of checking prevents the class of incident that takes a day to diagnose.

The automations I run for Ajust move case data through Airtable and WhaleSync on a schedule, and the thing I watch there is not whether jobs fail but whether they are getting slower. Duration drift is the leading indicator. Failure is the lagging one, and by the time you have it, something has already been wrong for a while.

What should you do next?

Build the table. Every scheduled job, its start time, its worst recent duration, and what it writes to. Nothing else in this article is possible without it, and most teams do not have it even when they think they do.

Then move everything off the top of the hour and off round numbers, and add an overlap guard to the longest-running job you own. Those two changes take an afternoon and remove the majority of collisions in a typical setup.

If you have a set of automations that mostly work and occasionally produce numbers nobody can explain, reach out. Scheduling is one of the first things I check, and it is a much more common cause than people expect.

Get found, cited and the back office automated

Let's make your site the source AI engines quote and wire up the systems behind it.

Contact

Let's get your website found and cited by AI

Tell me what you're working on, whether AI search is skipping your product, your back office is buried in manual work, or you need a build that does both.

Got it, thanks. I read every message personally and reply within 1-2 business days.
Oops! Something went wrong while submitting the form.