wispwisp
Primitives

Schedule

Cron and rate expressions on EventBridge Scheduler — no server to keep warm.

Declaring a schedule

Unlike every other primitive, the handler is passed straight to the constructor rather than a follow-up method call:

import { Schedule } from "@vorynza/wisp";
import { heartbeats } from "./stores/heartbeats.ts";

export const heartbeat = new Schedule("heartbeat", { expression: "rate(5 minutes)" }, async () => {
  await heartbeats.put({ id: "latest", firedAt: new Date().toISOString() });
});
OptionTypeDescription
expressionstringRequired. cron(...) or rate(...), EventBridge Scheduler syntax.
timezonestringOptional. An IANA timezone name, e.g. "Africa/Lagos". Applies to cron expressions.
export const nightly = new Schedule("nightly", { expression: "cron(0 2 * * ? *)", timezone: "Africa/Lagos" }, async () => {
  // runs at 02:00 in Africa/Lagos, every day
});

Error handling

A schedule invocation is a single unit of work — there's no partial-failure contract to implement the way there is for Queue. If your handler throws, the error is logged and rethrown; EventBridge Scheduler's own retry policy takes over from there.

What this deploys to

An AWS::Scheduler::Schedule and its own dedicated AWS::IAM::Role, trusted by scheduler.amazonaws.com and scoped to invoke exactly this one function — separate from the function's own execution role, which only ever gets permissions for what the handler's code touches (a Store, a Queue, ...). EventBridge Scheduler invokes the target directly with that role; there's no AWS::Lambda::Permission involved the way there is for API Gateway.

On this page