How schedules reach production: declare each @plugin.cron task in your manifest's "cron" array (see below) and the platform fires it per installed server — UTC, a 5-minute floor, up to 5 entries. @plugin.schedule (fixed intervals) runs only in local yourbot dev; for interval-style work in production use a cron spec or the event-driven pattern on Pool mode.
@plugin.schedule(seconds) runs a regular (synchronous) function on a fixed interval, starting after the first interval has elapsed. Do not declare it async def: nothing awaits it, so an async body would never execute. Keep intervals at 30 seconds or more; tighter loops burn your CPU allowance and get flagged in review.
@plugin.schedule(300) # every 5 minutes
def heartbeat(ctx: Context):
count = ctx.kv.increment("heartbeats")
ctx.log(f"heartbeat #{count}")
Runs never overlap — the next interval is counted from when the previous run finishes, so a slow handler delays later runs rather than stacking them.