Scheduled self-maintenance
The problem: anything operational decays. Tokens expire, failed jobs need retries, old records pile up, external state drifts. Traditionally this is a crontab on a server someone has to remember exists.
The pattern: a scheduled handler that treats maintenance as ordinary
document work — read state, decide, write it forward — so the app keeps
itself alive.
jsexport const config = { scheduled: { interval: "1m" } };
export async function scheduled(event, ctx) {
const vault = await ctx.db.query({ db: "vault" }); // admin mode: unfiltered
for (const cred of vault.filter((d) => d.kind === "token")) {
if (needsRotation(cred, event.scheduledTime)) {
try {
const fresh = await rotate(cred); // fetch() to the platform's API
await ctx.db.put({ ...cred, token: fresh.token, refreshedAt: event.scheduledTime, needsReauth: false });
} catch (e) {
await ctx.db.put({ ...cred, needsReauth: true, lastError: String(e && e.status) });
}
}
}
}
meta-hub runs this shape every
minute in production: it refreshes Meta's 60-day tokens once they're older
than 7 days, verifies fresh pastes via the platform's /me endpoint, probes
its own egress lanes, and advances pending publish requests — all from one
tick function.
The discipline that makes ticks safe
A 1-minute timer amplifies every mistake, so the production rules:
- Idempotent ticks. Each tick reads current state and converges it; a missed or doubled tick changes nothing. Never accumulate work in handler memory — the documents are the state.
- Bound your retries on the doc. An
attemptscounter and aMAX_ATTEMPTScap turn infinite retry loops intoerrorstates a human can see. Meta containers that aren'tFINISHEDjust retry next tick — bounded. - Respect upstream rate limits structurally. Bluesky's
createSessionallows ~300/day — so meta-hub mints session JWTs from a cached session and touches the password-based call only as a fallback, never on the timer. - Degrade to a visible state, never to silence… and never to noise. A
dead credential flips
needsReauthand the dashboard showsNEEDS RE-AUTH; held work resumes untouched after a fresh paste. Failures write status docs — they don't post, don't spam, don't lose the queue. - Keep admin-mode writes small.
scheduledruns as the owner with the access override (guide), so a buggy write fails silently-wrong rather thanforbidden. Small, well-guarded writes.
Composes with
The write-only vault (rotation is why the vault holds data, not config), doc state machines (the tick is the queue's consumer), and the operator console (every tick's status writes are the dashboard's live feed).