Skip to content

Runtime API

The full surface of the Runtime instance returned by App.runtime.

Dispatching

dispatch(action, input, envelope?)

ts
runtime.dispatch<TInput, TResult>(
  action: ActionDefinition,
  input: TInput,
  parentEnvelope?: MessageEnvelope,
): Promise<TResult>

Runs the action's handler through middleware → retry loop. Publishes any events the handler returned. Returns the handler's raw return.

Omit parentEnvelope for a fresh root envelope (typical for HTTP entry). Pass an envelope to chain — derives a child envelope sharing the correlationId.

publish(events, parentEnvelope)

ts
runtime.publish(events: readonly EventMessage[], parentEnvelope: MessageEnvelope): Promise<void>

Internal — applies events to actors / projections / reactions. Mostly used by tests + rare external publishes. Handlers should return events rather than calling publish directly.

applyExternalEvent(eventName, payload, envelope)

ts
runtime.applyExternalEvent(eventName: string, payload: unknown, envelope: MessageEnvelope): Promise<void>

Applies an event that arrived from the cross-service bus. Same pipeline as publish but does NOT re-publish to the bus — avoids fan-out loops.

Throws if the event name wasn't declared in any module's needs.externalEvents.

Querying

query(name, input, tenant?)

ts
runtime.query<TResult>(name: string, input: unknown, tenant?: string): Promise<TResult>

Runs a registered query by name. Use ctx.query(queryDef, input) from handlers (auto-threads tenant); use this from tests / scripts.

Telemetry

onTelemetry(listener)

ts
runtime.onTelemetry(listener: (rec: Telemetry) => void): () => void

Subscribe to the canonical telemetry stream. Returns an unsubscribe function. Throws in listeners are caught + console-logged.

offTelemetry(listener)

ts
runtime.offTelemetry(listener: (rec: Telemetry) => void): void

Detach a listener explicitly. Equivalent to calling the unsubscribe function returned by onTelemetry.

Middleware

use(middleware)

ts
runtime.use(middleware: DispatchMiddleware): void

type DispatchMiddleware = (
  next: () => Promise<EventMessage | EventMessage[] | void>,
  action: ActionDefinition,
  input: unknown,
  ctx: HandlerContext,
) => Promise<EventMessage | EventMessage[] | void>

Onion-style. Outermost-first registration order. Runs OUTSIDE the retry loop — one pass per dispatch.

Registration

Used by createApp internally; rarely called directly.

ts
runtime.registerHandler(handler: HandlerDefinition): void
runtime.registerActor(actor: ActorDefinition): void
runtime.registerProjection(projection: ProjectionDefinition): void
runtime.registerQuery(query: QueryDefinition): void
runtime.registerWhen({ eventName, handler }): void
runtime.registerExternalEvent(eventName: string): void
runtime.registerPublicEvent(eventName: string): void
runtime.registerExternalCall(def: ExternalCallDefinition): void
runtime.registerExternalCallExecutor(def, executor): void
runtime.registerActorTransitionHook(hook): void

Introspection

ts
runtime.listHandlers(): readonly string[]
runtime.listActors(): readonly string[]
runtime.listProjections(): readonly string[]
runtime.listQueries(): readonly string[]
runtime.listExternalCalls(): readonly string[]

runtime.getExternalCall(name): ExternalCallDefinition | undefined
runtime.getActorStore(): ActorStore
runtime.getProjectionStore(): ProjectionStore
runtime.getContainer(): Container
runtime.getDeadLetterSink(): DeadLetterSink

Timers

fireDueTimers(now?)

ts
runtime.fireDueTimers(now?: number): Promise<number>

Walks every actor instance; dispatches actions for timers with fireAt <= now. Returns count fired. Idempotent — fired timers are removed.

For tests: pass now = Date.now() + 3 * 86400_000 to fast-forward 3 days. In production: a transport (BullMQ scheduler, polling worker) calls this on an interval.

External calls

executeExternalCall(def, request, envelope?)

ts
runtime.executeExternalCall<TReq, TResp>(
  def: ExternalCallDefinition<TReq, TResp>,
  request: z.output<TReq>,
  envelope?: MessageEnvelope,
): Promise<z.output<TResp>>

Used by ctx.externalCall(...) internally. Validates request, threads idempotency key, applies retry policy, emits telemetry, calls the registered executor.

See also

MIT licensed.