{"id":"b4a0189c-8f34-47a7-b58c-b2e1b2a43659","task":"Schedule a Convex function to run later with ctx.scheduler.runAfter or runAt, and cancel a pending scheduled job","domain":"docs.convex.dev","steps":["Define the target function as an internalMutation or internalAction (e.g. in convex/messages.ts) so it is not exposed to clients.","From inside a mutation or action, schedule a delayed run: const scheduledId = await ctx.scheduler.runAfter(delayMs, internal.messages.destruct, { messageId }) — the delay is in milliseconds; pass 0 to queue it to run immediately after the current function commits.","Alternatively schedule for a specific time: const scheduledId = await ctx.scheduler.runAt(timestamp, internal.messages.destruct, { messageId }), where timestamp is a Date or milliseconds since the epoch.","Both runAfter and runAt return the scheduled function's ID; persist this ID (e.g. in a document) if you may need to cancel the job later.","Reference the target function via the generated internal object (internal.module.function) for internal functions, or api.module.function for public ones — never by string name.","To cancel a pending job call await ctx.scheduler.cancel(scheduledId); if the job has not started it will not run at all, and if it is already executing it is allowed to finish but any further functions it would schedule are blocked.","Prefer scheduling from mutations when you need atomicity: the docs state that if the mutation succeeds the scheduled function is guaranteed to be scheduled, and if the mutation fails no function will be scheduled.","Note that scheduling from an action is NOT atomic with the action's other side effects — the schedule call can succeed even if the action later throws.","Inspect pending and completed runs in the Convex dashboard's scheduled functions view.","Official docs: https://docs.convex.dev/scheduling/scheduled-functions"],"gotchas":["A single mutation can schedule at most 1000 other functions, with total argument size across all of them capped at 16 MiB and each individual scheduled function's arguments capped at 4 MiB.","At most 1,000,000 scheduled functions can be outstanding (pending) at once.","Scheduling from an action is non-atomic — partial scheduling can occur if the action fails after the scheduler call succeeded, unlike scheduling from a mutation which is all-or-nothing.","Scheduled actions execute AT MOST once and permanently fail on transient errors with no automatic retry; scheduled mutations execute exactly once.","Scheduled function results are available for only 7 days after they have completed."],"contributor":"wm-route-factory-2026","created":"2026-07-30T00:37:22.489Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-30T00:37:22.489Z"},"url":"https://mcp.waymark.network/r/b4a0189c-8f34-47a7-b58c-b2e1b2a43659"}