Skip to content

Durability API

Creates a durability runtime and one typed operation method per handler.

Every handler receives:

FieldMeaning
idStable call and idempotency key
operationRegistered handler name
payloadInferred handler payload
attemptOne-based attempt number
signalAttempt-scoped AbortSignal
type DurableHandler<TPayload, TResult> = (
call: DurableCall<TPayload>
) => TResult | Promise<TResult>;
OptionPurpose
alarmConcurrencyMaximum immediate operations run by an alarm pool
backgroundConcurrencyMaximum operations run by the timer pool
alarmHandoffMsTime before an alarm returns and hands pending work forward
attemptTimeoutMsDefault timeout for one handler attempt
retries.maxAttemptsDefault total attempt limit
retries.jitternone, equal, or full backoff jitter
methodsPer-operation timeout and retry overrides

For a handler named sendEmail:

await durability.sendEmail({ id, payload });
await durability.background.sendEmail({ id, payload });
const immediateResult = await durability.sendEmail.getResult(id);
const backgroundResult = await durability.background.sendEmail.getResult(id);

Both enqueue methods resolve after registration. Both result methods return:

  • { status: 'not_found' }
  • { status: 'pending', attempt, nextAttemptAt, lastError }
  • { status: 'failed', attempt, error }
  • { status: 'completed', attempt, result }

Runs due calls and schedules the next alarm. Delegate the Durable Object alarm() method directly to it.

Moves package storage to a named migration or to null for a complete rollback.

Marks the current call as terminal without another attempt.

Signals that an operation ID was reused for a different operation. IDs must be unique across the Durability instance, not only within one handler.

@durability/lint provides Oxlint rules that enforce alarm delegation and namespaced migration ownership:

{
"jsPlugins": [
{ "name": "durability", "specifier": "@durability/lint" }
],
"rules": {
"durability/alarm-runner-only": "error",
"durability/durability-migrations-only": "error"
}
}