Runlane
ReferenceApplication API

Tasks and context

Task definitions, queues, retry rules, schedules, and handler APIs.

Import task, queue, the enums, and the types on this page from @runlane/core.

Task definition

task(options) returns a reusable task definition. Register that same definition in each process that executes the task.

OptionType and behavior
idRequired, nonempty task ID. Keep it stable across deployments. Colons are reserved.
schemaRequired Standard Schema for the payload. The handler receives the validated output.
runRequired handler: run(payload, context). Return output, undefined, a task release, or a promise of one of those values.
outputOptional Standard Schema for successful output. Enables typed reads with runlane.runs.get(task, runId).
queueOptional registered QueueDefinition. Falls back to the runtime's default queue.
retryOptional retry policy. Omit it to disable automatic retries.
maxAttemptDurationOptional DurationString that limits each attempt. Execution options can override it.
scheduleOptional static schedule or list of schedules, described below.
idempotencyKeyOptional string or (payload) => string | undefined. Reuses a run with the same key.
idempotencyKeyTTLOptional DurationString or IdempotencyKeyTTLMode.Active. Requires an idempotency key.
singletonKeyOptional string or payload resolver. Allows only one active run for the key.
concurrencyKeyOptional string or payload resolver. Shares capacity within a bounded queue.

Key resolvers receive the validated payload. Trigger options can override the task's key settings.

Payloads and outputs must be JSON-compatible, or undefined where the schema allows it. Payload validation and transforms run when the run is created. Later attempts reuse the stored payload. Changing a task's schema does not migrate old runs.

A successful handler's output is validated before storage. A typed read validates the stored output against the supplied task's current output schema. Keep that schema compatible with retained results.

See define and trigger tasks for a complete example.

Retry policy

retry accepts these fields:

FieldType and behavior
maxAttemptsRequired positive integer. A failure can retry only while the run's attempt count is below this limit. Includes the first attempt and attempts that ended in a release.
backoffOptional DurationString for a fixed delay, or the object below. Defaults to contractDefaults.retry.backoff.

A backoff object requires type and delay:

FieldType and behavior
typeRetryBackoffType.Fixed or RetryBackoffType.Exponential.
delayDurationString for the base delay. Fixed backoff uses it for every retry. Exponential backoff uses delay × 2^(attempt - 1) before applying the cap.
maxDelayOptional DurationString that caps the delay. Must be at least delay.

The attempt number includes attempts that ended in a release. There is no automatic jitter. Set a policy based on the service you call and the time available for recovery.

With a retry policy, an ordinary thrown Error is retryable. A RunlaneError uses its own retryable field, which defaults to false. A retry still requires a task policy and remaining attempts. Attempt timeouts also follow that policy.

See retry failed work for a task that retries temporary failures and stops on a permanent failure.

Queue definition

queue(options) returns a QueueDefinition.

OptionType and behavior
nameRequired, nonempty queue name. Colons are reserved.
defaultOptional boolean, default false. At most one registered queue may be the default.
concurrencyLimitOptional positive integer. Caps shared execution capacity through storage. Omit it for an unbounded queue.
dispatchTimeoutOptional DurationString. Requires concurrencyLimit; controls recovery of a dispatched capacity reservation.

Use matching queue definitions in producers, workers, and maintenance processes. A task's concurrencyKey requires a bounded queue. See limit concurrency for capacity behavior.

Schedules

Set schedule on the task to one schedule or a list. Each entry needs a stable id and a payload accepted by the task. Omit the payload only when the task schema accepts undefined. All entries also accept queue?: QueueDefinition and enabled?: boolean.

Choose one timing form per entry:

FormFields
OncerunAt: Date
Intervalevery: DurationString, with optional startsAt: Date and endsAt: Date
Croncron: string, with optional timeZone: string

These are static task definitions, not a runtime schedule editing API. Maintenance must register the tasks and run to create due occurrences. See schedule tasks.

Handler context

Every handler receives a TaskContext as its second argument. A resumed attempt starts the handler again from the beginning.

MemberBehavior
runCurrent RunRecord, including the run ID and stored payload.
attemptCurrent attempt number. A resumed release starts another attempt.
signalAbortSignal for cancellation, shutdown, or an attempt deadline. Pass it to fetch() and other work that supports it.
isCancellationRequested()Returns whether operator cancellation has been requested.
trigger(task, payload, options?)Returns Promise<TriggerRunResult>. Creates a child run linked to the current run. Takes the runtime trigger options.
release(delay, options?)Returns TaskRelease. delay is a DurationString; options are reason?: string and meta?: JsonObject.
waitForRun(runId, options?)Returns TaskRelease. Waits for another run to end. Options are reason, timeout: DurationString, and meta, all optional.
waitForSignal(signalKey, options?)Returns TaskRelease. Waits for a matching signal, with the same optional fields as waitForRun().

Return a release or wait from the handler. These methods create a return value; they do not suspend the JavaScript call stack. A release records no failure. Its next attempt still advances the attempt count used for later retry decisions.

A signal carries no stored result. On every resumed attempt, read the saved application state before deciding whether to wait again. A signal sent before a waiter exists is not saved. See wait without failing for a complete example with a timeout that recovers from a missed signal.

Durable steps

context.step.run(stepKey, { output: schema }, callback) returns a promise of the schema's output. The callback receives { token }.

The first successful call saves its validated result under that key within the run. Later attempts reuse that result and skip the callback. The callback can still run again if the process stops before the result is saved. Pass token as the external service's idempotency key when it supports one.

Keep step keys stable and unique for each operation within a run. Saved results are reused without applying a new schema transform. See save step results.

Context wait tokens

CallReturn value
context.wait.createToken(options?)Promise<CreateWaitTokenResult>. Uses the same creation options as the runtime token API.
context.wait.getToken(tokenId, { output: schema })A promise of a typed token or undefined. Validates a completed token's output.
context.wait.forToken(tokenId, options?)TaskRelease. Optional reason and meta describe the wait. The deadline belongs to the token.

Return context.wait.forToken() while the token is pending. On the next attempt, read the token and handle completed or timed_out. See runs and waits for external token operations and build a human-in-the-loop flow for the full pattern.

On this page