Runlane
Build providers

Transport provider

Publish wakeups and connect a broker-native worker to Runlane.

A transport provider connects Runlane to a broker such as SQS. The broker carries wakeups. Storage still holds the task payload and current run state.

A complete transport provider has two sides:

Runlane outbox --> TransportDriver.publish() --> broker

broker --> ProviderDeliverySurface --> Runlane worker
                                      |
                                      v
                              handled / retry / reject

Import both contracts from @runlane/contracts.

Publish wakeups

TransportDriver.publish() receives a bounded array of messages. Each message already has canonical bytes, an outbox id, a logical queue, and an optional partition key.

The provider may group messages by destination or split them into native batches. It must return one outcome for each input, at the same array index.

What happenedWhat the provider returns
The broker accepted one itempublished at that item's index
One item failed and the result is certainfailed at that item's index
The whole request failed and item results are unknownReject the call

Do not change the canonical message bytes. Return copies of mutable bytes and dates.

Deliver wakeups

ProviderDeliverySurface connects a native consumer to one Runlane DeliveryProcessor.

For each broker message:

  1. Read its Runlane bytes.
  2. Pass the bytes to the processor.
  3. Map the returned disposition to the broker action.
Runlane dispositionBroker action
handledAcknowledge, delete, or commit the message
retryLeave it available for another delivery
rejectComplete the configured terminal action

If terminal handling fails, do not acknowledge the original rejected message. An unexpected processor error is retryable.

The provider owns receipt handles, offsets, visibility extensions, consumer groups, dead-letter configuration, and settlement. Those details do not enter core.

Choose the worker shapes

A provider can expose either or both:

  • createWorker() for a long-running receive loop;
  • createHandler() for a platform-native serverless handler.

A long-running worker must support cooperative close() and observable waitUntilClosed(). Repeated closes should be safe. A background failure must reject waitUntilClosed().

Keep a serverless handler's native type in the lane generic. Do not add platform-specific event unions to Runlane core.

Report the real transport profile

Declare:

  • maximum bytes in one message;
  • maximum messages in one publish call;
  • durability after the broker acknowledges a publish;
  • whether ordering is absent or preserved within a partition for messages the broker accepts.

Broker ordering and Runlane queue concurrency are separate controls.

A failed per-message publish outcome has no broker position. If the caller retries it later, that retry is a later publish and may follow messages the broker already accepted from the original command. Do not claim original-command ordering across rejected entries unless the provider implements a durable sequencer or an equivalent guarantee.

Expect duplicate wakeups

A publish can succeed just before the publisher loses the response. Brokers can also redeliver messages.

Pass every valid wakeup to core. Do not treat the broker message as the job or invent provider-side run state. Core re-reads storage and decides whether the run can execute.

Prove the provider

Test batch results, partial failures, settlement, malformed messages, visibility or lock refresh, ordering, cancellation, and shutdown. Then run the same cases against the real broker.

Continue with test a provider. @runlane/transport-sqs is the shipped reference implementation, and the exact stable values are in delivery values.

On this page