Install and quickstart
-
Install the package
Terminal window npm install durability -
Create a SQLite Durable Object migration
{"migrations": [{ "tag": "v1", "new_sqlite_classes": ["EmailJobs"] }]} -
Define typed handlers
import {createDurability,NonRetryableError,type DurableHandler,} from 'durability';const handlers = {sendEmail: (async ({ id, payload, attempt, signal }) => {const response = await fetch(payload.url, {method: 'POST',headers: {'Content-Type': 'application/json','Idempotency-Key': id,},body: JSON.stringify(payload.message),signal,});if (response.status === 400) {throw new NonRetryableError('Email request is invalid');}if (!response.ok) {throw new Error(`Email request failed: ${response.status}`);}return { attempt, messageId: await response.text() };}) satisfies DurableHandler<{ url: string; message: string },{ attempt: number; messageId: string }>,}; -
Create Durability and delegate the alarm
export class EmailJobs extends DurableObject<Env> {private readonly durability = createDurability(this.ctx, handlers);send(userId: string, payload: Parameters<typeof handlers.sendEmail>[0]['payload']) {return this.durability.sendEmail({id: `welcome:${userId}`,payload,});}alarm(info?: AlarmInvocationInfo) {return this.durability.alarm(info);}}
Read a typed result
Section titled “Read a typed result”const result = await this.durability.sendEmail.getResult(`welcome:${userId}`);
switch (result.status) { case 'not_found': break; case 'pending': console.log(result.attempt, result.nextAttemptAt, result.lastError); break; case 'failed': console.error(result.error.name, result.error.message); break; case 'completed': console.log(result.result.messageId); break;}The completed value is inferred from the handler return type. Looking up an ID owned by another operation throws DuplicateDurableCallError instead of returning a value with the wrong type.
Schema management
Section titled “Schema management”createDurability applies package migrations and stores operations in durability_calls, named schedules in durability_alarms, and migration history in durability_migrations.
import { migrateDurability } from 'durability';
migrateDurability(this.ctx, 'durability_0001_create_calls');migrateDurability(this.ctx, null);