Patterns

A catalog of things you can do with DelayKit

Each pattern maps a concrete problem to the DelayKit API. If you’re not sure which one you need, start with Send a reminder or Debounce a flurry.

Wake an agent after a timeout

Schedule a timeout for an agent run waiting on human input. The handler resumes the run if approval doesn't arrive.

dk.schedule("agent-timeout", { delay: "24h" })
cancel when approval arrives

Send a reminder

Schedule a notification for later. The handler checks current state when it fires.

dk.schedule("remind", { delay: "24h" })
handler decides whether to send

Expire something

Run a side effect (email, cleanup, notification) when an invitation, checkout hold, or magic link expires. Handler reads current state and skips if the user already acted.

dk.schedule("expire-invitation", { delay: "7d" })
handler skips if the user already accepted

Debounce a flurry

Collapse fifty events into one action. Durable across restarts.

dk.debounce("reindex", { wait: "5s" })
optional maxWait to cap the window

Retry with backoff

Defer a failed operation to a durable retry with exponential backoff. Worked examples for Stripe (idempotency-key handling for timeouts and custom dunning); same shape applies to CRM syncs, webhook deliveries, and any external call that occasionally fails.

dk.schedule("retry-charge", { delay: "30s" })
reuse the idempotency key when retrying the same attempt

Coalesce into a digest

Collapse a burst of events into one handler run per window. The handler fires at the end of the window with the latest state.

dk.throttle("digest", { wait: "1m" })
one handler run per window, many calls coalesce

Schedule a follow-up

Fire a task only after activity goes silent. Each event resets the clock with a single DB update, no scheduler churn.

dk.debounce("follow-up", { key, wait: "3d" })
single DB update per call, no scheduler reschedule

Deferred cleanup

Fire-and-forget maintenance. Schedule it once, let it run.

dk.schedule("cleanup", { delay: "1h" })
no state check, no cancel, just runs

Renew before expiry

Refresh a token, lease, or session a few minutes before it expires. Worked examples for Google and Slack v2 OAuth (with refresh-token rotation); the same shape applies to GitHub Apps, presigned URLs, and any time-bound credential.

dk.schedule("refresh-google", { at: renewAt })
reschedule on each successful renewal

Poll until done

Wait on an async job by checking back periodically until it's done, or until you give up. Useful for Replicate predictions, OpenAI batch jobs, and Mux transcodes.

dk.schedule("check-prediction", { delay: "2m" })
handler reschedules itself until status is terminal

Schedule a drip sequence

Schedule every step of an onboarding or trial drip up front. Each handler checks current state when it fires.

dk.schedule("drip-day-3", { delay: "3d" })
one job per step, all queued at signup

Delayed publish

Publish a post, send an email, or release content at a specific future time.

dk.schedule("publish", { at: post.publishAt })
edit or cancel any time before it fires