State and Runtime Boundaries
This page explains where backend state lives, which parts are durable, and how TaskBridge separates transport runtime concerns from task execution concerns.
Core state interfaces
The main durable boundaries in backend core are:
TaskRegistryEventStoreSuspensionStoreActionReceiptStore
These are the stores TaskBridge depends on to make idempotency, replay, and action resumption reliable.
What each store owns
TaskRegistry owns:
- task records;
- task status transitions;
- idempotency lookup by
clientRequestId; - cancellation requested state.
EventStore owns:
- ordered task event history;
- replay after an event cursor;
- durable event IDs used by client resume flows.
SuspensionStore and ActionReceiptStore own:
- durable record of task suspensions;
- accepted client actions;
- pending resume handoff state;
- expiration and reconciliation inputs.
State boundary map
flowchart LR
Registry[TaskRegistry] --> TaskState[Task records and status]
EventStore[EventStore] --> EventState[Replayable task events]
Suspension[SuspensionStore] --> HumanState[Suspensions and pending resumes]
Receipts[ActionReceiptStore] --> ActionState[Accepted client actions]
Executor[TaskExecutor] --> Runtime[Workflow runtime]
Replay and stream runtime
Replay semantics are stable at the service and protocol level, but transport runtime settings are configurable.
Relevant runtime settings objects:
SseStreamSettingsWebSocketStreamSettingsStreamRuntimeSettings
These control stream behavior such as:
- heartbeat emission;
- wait timeout tuning;
- runtime-specific close behavior.
Use them when hosts need operational tuning. Do not use them to redefine the protocol itself.
Durable vs ephemeral boundaries
TaskBridge backend durable state:
- task records;
- replayable event history;
- accepted action receipts;
- pending resume handoffs.
TaskBridge backend ephemeral runtime state:
- live SSE generator loop;
- WebSocket connection state;
- heartbeat timing;
- in-flight request handling.
Runtime adapter durable state:
- workflow state inside Temporal or another execution engine.
This split prevents the transport layer from becoming the workflow engine.
Resume and reconciliation
TaskResumeService is the host hook for continuing a suspended task after a durable action accept.
TaskResumeReconciliationService exists because resume handoff may fail after the action was already durably accepted.
That means:
- action acceptance must be durable first;
- resume dispatch can be retried later;
- reconciliation is part of correctness, not just cleanup.
Resume flow
sequenceDiagram
autonumber
participant Client as Client
participant Action as TaskActionService
participant Suspend as SuspensionStore
participant Receipt as ActionReceiptStore
participant Resume as TaskResumeService
participant Recon as Reconciliation service
Client->>Action: submit_action
Action->>Suspend: accept_action_if_open
Action->>Receipt: save accepted receipt
Action->>Resume: resume_task(...)
Note over Resume: If dispatch fails after durable accept
Recon->>Suspend: list_pending_resume_handoffs
Recon->>Receipt: load accepted receipt
Recon->>Resume: retry resume_task(...)
Retention
TaskRetentionService is the cleanup boundary for expired receipts and suspensions.
This is operationally important because action and suspension correctness depends on durable state, but that state must still be pruned over time.
What not to conflate
EventStoreis not your workflow engine state store.TaskRegistryis not a replacement for domain-specific job metadata.- WebSocket or SSE runtime settings do not change backend protocol semantics.
- action receipt durability and resume dispatch are related but not identical concerns.