Skip to content
Changelog

Report a bug

Keep State Between Runs

Each run starts in a new VM. Variables, class fields, and files do not stay after the run. Use a checkpoint to keep state for the next run.

src/main.ts
import type { AutomationContext, RecurringEvent } from "@type-dot-com/sdk/automations";
import { err } from "neverthrow";
import { z } from "zod";
const stateSchema = z.object({ lastSeenId: z.string() });
export default class {
async check(ctx: AutomationContext, event: RecurringEvent) {
// 1. Read the state from the last successful run.
const previous = stateSchema.safeParse(ctx.checkpoint?.value);
const lastSeenId = previous.success ? previous.data.lastSeenId : null;
// 2. Do the work.
const newestId = await findNewestId(ctx, lastSeenId);
if (newestId.isErr()) return err(newestId.error);
// 3. Save the state for the next run.
const saved = ctx.saveCheckpoint({ lastSeenId: newestId.value });
if (saved.isErr()) return err(saved.error);
return ctx.setOutput({ lastSeenId: newestId.value });
}
}
  • ctx.checkpoint is null until a run saves a checkpoint.
  • ctx.saveCheckpoint(value) stages the value. Type saves it only when the method succeeds.
  • If the run fails, Type keeps the old checkpoint. The next run starts from the old state.
  • Each subscription has its own checkpoint.
  • The checkpoint stays when you deploy new code. If you rename the subscription key, the new key has no checkpoint.
  • The value must be JSON. All results of a run must fit in 2 MiB of JSON together: the checkpoint, output, report, handoffs, and action logs.

Checkpoints and external writes are not atomic

Section titled “Checkpoints and external writes are not atomic”

Type saves the checkpoint after the method succeeds. It does not save it in the same step as a message or an API write. Plan for these cases:

  • The write succeeds, then the run fails before the checkpoint is saved. The next run can do the same write again.
  • The write has an unknown result because of a timeout.

To make a repeat safe, use a stable effect key, and read the destination before you write. See Write Safely.

Type already does some work for you:

  • Type does not run the same event two times for the same subscription.
  • Matchers and resources filters remove events before your code runs.
  • Recurring sources give each run its own scheduledAt time.

Do not add a checkpoint only to repeat this work. Use a checkpoint for progress that your workflow needs, for example the last item that you processed.

  • Saved data: ctx.read.data.read() and ctx.read.data.list() read data that is saved for this automation. Automation code cannot write it.
  • Sandbox files: Files in the sandbox can stay between runs, but Type can replace the sandbox at any time. Use sandbox files only as a cache.
  • Run output: ctx.setOutput() shows a result in run history. Later runs cannot read it.