Primitives
The small set of ideas Runlane builds on.
Runlane is built from a small set of durable primitives. Every feature, adapter, worker, and operator action is a composition of these ideas.
The core idea is simple: user code is not the durable thing. A run is.
task + payload
-> durable run
-> append-only events
-> materialized run state
-> worker or delivered wakeup executes one attemptA task defines user code, a payload schema, and execution policy. A run is one durable execution record for that task and payload. Events record what happened. Storage persists events and the current run state atomically. Transport only wakes workers; it never decides whether a run exists or what state it is in.
One model, three job shapes
Runlane supports three product shapes, but they all create or continue the same run model:
- Background jobs: application code triggers durable work that can run outside the request path.
- Scheduled jobs: task-colocated schedules materialize durable runs at a time or cadence.
- Polling jobs: a task releases its run to continue later without counting the wait as a failure.
See Job Shapes for how these map to real workloads. The important part is that scheduled work and polling work are not separate execution engines. They create or resume durable runs, and workers execute those runs through the same lifecycle as any other work.
The normal lifecycle
A typical background run looks like this:
trigger()
-> run.created
-> run.delivery_requested
-> worker claims lease
-> task handler runs
-> run.succeeded | run.failed | run.retry_scheduled | run.released | run.cancelledrunNow() is the current-process exception. It creates the run, claims the first lease, and executes exactly that run inline. It still writes durable history and uses the same task execution path after the lease is claimed. See Current-Process Execution.
Primitive map
Read the concepts in nav order when you are learning Runlane for the first time:
- Job Shapes explains background, scheduled, and polling work.
- Tasks And Runs defines user code, payload validation, ids, idempotency, singleton keys, concurrency keys, runs, and events.
- Queues explains provider-neutral routing and durable queue capacity.
- Workers explains polling workers, drain workers, delivered wakeups, leases, and heartbeats.
- Current-Process Execution explains
runNow()and when inline durable execution is the right path. - Schedules explains once, interval, and cron schedules that materialize ordinary runs.
- Retry Vs Release explains the difference between failure pressure and business waiting.
- Operator APIs explains run reads, attempts, events, cancellation, rerun, manual retry, idempotency reset, and pruning.
- Cancellation explains cooperative stop requests for queued and running work.
- Rerun And Manual Retry explains linked recovery runs without mutating terminal history.
- Pruning explains retention for old terminal run data.
- Lanes, Storage, And Transport explains why storage owns truth and transport only publishes wakeups.
- Local Development explains the in-memory local lane for development and tests.
Boundaries that matter
Runlane keeps product behavior in core and durable truth in storage:
@runlane/core
task registration, triggering, schedules, retry, release, workers, operators
storage adapter
events, materialized runs, leases, schedules, outbox rows, indexes, pruning
transport adapter
wakeup publishing and provider acknowledgementsThis split is why delayed, duplicate, or missing transport messages do not decide run state. A worker or transport consumer always reads the current run from storage before executing. If the run is terminal, not due, on the wrong queue, or already leased, the wakeup is ignored safely.
It also means tick() is part of the runtime model. Maintenance materializes due schedules, requests delivery for released or retrying runs, recovers expired leases, finalizes abandoned cancellations, and flushes pending outbox rows.
Picking the right first page
If you are defining work, start with Tasks And Runs. If you are deciding how work gets executed, read Queues and Workers. If you are modeling "try again later," read Retry Vs Release before writing task code. If you are wiring infrastructure, read Lanes, Storage, And Transport before choosing or authoring adapters.