Autoretto.
← All posts
Engineering notes · June 10, 2026 · 3 min read · Autoretto Daily

Why your scheduled uploads now fire even with no browser open

For a while there was a quiet problem hiding in the scheduling code, and it is worth being honest about it. The schedule knew when your next release should land. It could show you the slot. It could explain why it picked that day and that hour. What it could not always do was actually fire when nobody was looking.

The reason was subtle. On a serverless host, every request runs on a fresh, short-lived instance with no memory of the last one. When a scheduled run was triggered, the code would load your schedule and compute the next release time. But "next release time" always points at the future by definition. So the check that asked "is anything due right now" looked at a time that had just been pushed forward, decided nothing was due, and quietly did nothing. The slot you wanted was always one step ahead of the thing meant to catch it.

The fix is small once you see it. Instead of asking "is the next future slot in the past", which can never be true, the scheduler now looks at the most recent slot that has already passed. If that slot passed within a sensible catch-up window, and we have not already published for it, it fires. The window absorbs a late or missed run without ever reaching back days to revive an old slot.

There is a second piece that keeps this safe. The moment a slot fires, the scheduler stamps the release time and writes it to the database before the heavy work begins. If two instances happen to wake up at once, the second one rehydrates that stamp, sees the slot was already served, and steps aside. No double uploads. The publish step also re-checks your weekly quota from a fresh read, so even in the worst case nothing slips through twice.

The catch-up window matters more than it sounds. Crons are not perfectly punctual. A run can be delayed, or one can be skipped entirely if the platform is busy. So instead of demanding that the cron fire at the exact second of the slot, the scheduler accepts any slot that passed in the last couple of hours and has not been served yet. That absorbs a late tick without drama. It also refuses to reach back further than that, so a channel that was just discovered by the cron does not suddenly publish a release for a slot that passed days ago. The window is wide enough to be forgiving and narrow enough to stay sane.

It is worth saying what we did not do, because it is tempting. We did not keep a long-lived process alive just to hold a timer in memory. That works on a normal server and falls apart the moment you run on something that spins instances up and down. Leaning on a timer would have meant the schedule only worked while a machine happened to be warm. Keying off the clock and the database instead means the schedule has no warm-up requirement at all. Any instance, cold or hot, can look at the time, look at the slots, and do the right thing.

We also wrote a test that fails the old way and passes the new way, which is the part that keeps this honest going forward. The test sets a slot, moves the clock to just after it, and asserts the release fires. It moves the clock too early and asserts it does not. It stamps a release and asserts the same slot will not fire twice. None of that sounds dramatic, but a green check on those four cases is the difference between a schedule you can walk away from and one you have to babysit.

The lesson is an old one. A background job is only real if it survives the absence of a person. We test for that now, and the cron that drives it runs on a fixed interval whether or not a single browser tab is open anywhere in the world. Your slots fire because the clock fires them, not because you happened to be watching.