Queues and Workflows
Reviewed 5 October 2026. This is the Cloudflare execution profile of Tidemark, Bus and Work. Work's selected replacement removes Meeseeks: WorkStore owns admission/results, WorkRuntime owns bounded attempts and WorkScheduler supplies wakeups. Cloudflare Workflows owns remote step history; Queues and Pub/Sub adapters own delivery. Shared Reaktor Queue/Workflow execution adapters remain proposed. CompanyOS already contains a Workflow entrypoint; that implementation does not establish a reusable Reaktor executor or prove every step performs a business effect.
Choose the mechanism by responsibility
| Mechanism | Responsibility | Data-layer boundary |
|---|---|---|
| Cloudflare Queues | Buffered distribution of independent background commands with retries and batching | Work transport; no product authority, retained event history or ordering guarantee |
| Cloudflare Workflows | Durable multi-step execution, checkpoints, waits, retries and events | Orchestrates effects at their existing authorities; does not transact across stores |
| Durable Object / actor | Scoped coordination, admission, ownership, live state and provider-local transactions | Keep when single-writer state or session coordination is needed; no universal DO requirement |
| Pub/Sub / retained log | Independent subscribers, event distribution and qualified replay/ordering profiles | A work queue is not a replacement for fanout or a retained domain log |
| Mesh / WebSocket | Live progress, presence and ephemeral collaboration | Publish views of durable state; disconnecting does not cancel a committed job |
| Device scheduler | A local wakeup under the platform's execution constraints | A wakeup is not a durable server job or a completed effect |
Use a Queue alone for a bounded notification attempt or an index update. Use a Workflow for an export, connector reconciliation, staged media processing or a human approval. A Workflow can start directly from durable intent; putting a Queue in front is useful when admission needs buffering and rate control, not as a mandatory extra hop.
Durable intent and delivery
The proposed command envelope carries a stable effectId, tenant/application scope, operation and contract revision, input reference/revision/digest, correlation/causation, deadline and authorization reference. Queue message IDs, attempt numbers and random Workflow IDs are transport identities, not business deduplication keys. Keep credentials and large document/media bodies out of the envelope; resolve scoped secrets at execution and read content from its authorized store.
- Validate a command at the authority. Commit its domain change and delivery intent in the same local transaction, where that provider supports it. Otherwise define an explicit recoverable admission protocol; do not imply a cross-store transaction.
- A relay sends the intent to the Queue, or starts the Workflow. Publishing and marking the intent delivered can fail between operations, so retry with the original
effectId. - A consumer validates the envelope and current authority, then commits a bounded effect or hands off to a durable Workflow. Acknowledge only after that responsibility is durable.
- Record an effect receipt with its input fingerprint and source revision. Duplicate delivery returns the existing outcome; the same key with different input is a conflict.
The relay's accepted send means the broker accepted work. It does not prove a projection applied it, a notification reached a device or an export completed. Expose accepted, running, applied, failed, cancelled and reconciled states with evidence appropriate to the operation.
Queue consumer contract
Cloudflare Queues uses at-least-once delivery. A consumer must tolerate duplicates and reordering. A successful item can be acknowledged individually; a later failure need not force that item's redelivery. Bound concurrency and batch size to the downstream store/provider, classify permanent errors, and configure a dead-letter queue. Read delivery guarantees, batching and retries and DLQ behavior.
For state mutations, commit the effect and dedup receipt together in the same authority transaction, with a uniqueness constraint for concurrent duplicates. A check followed by a separate write is insufficient. For external effects, pass a stable provider idempotency key where supported; otherwise reconcile ambiguous outcomes before repeating them. A notification provider's acceptance is not evidence of exactly one user-visible delivery.
Respect ordering at the authority, not by relying on the Queue. A revisioned projection may conditionally apply a newer record snapshot, but an ordered sequence of ledger deltas must buffer/recover missing positions. Record the applied source position. Avoid calling a projection current merely because its consumer is active.
DLQ operations retain the original logical key, scope and input fingerprint. Inspection/redrive requires permission, a reason, a bounded selection and a receipt. Revalidate expired authority and deleted inputs. Retention and dedup horizons must cover scheduled delays, outage recovery and permitted redrive; provider retention is not the business audit record. Consult current Queue limits when choosing the deployment's capacity and retention.
Extending Workflows
Compile an admitted, revisioned Work definition into a provider-specific execution plan. Keep the definition, one logical run, provider instance, step and attempt as separate identities. Bind the run to its input snapshot/revisions and execution profile; an edited graph must not silently change the meaning of an existing run.
Follow Work's typed DAG laws: execute ready independent nodes with bounded concurrency, reuse committed dependency results, and preserve branch/join outcomes and dynamic child identities across recovery. A topological list executed sequentially does not establish parallel DAG evaluation. Cloudflare Workflows is the included durable backend; the capability comparison and measurement protocol distinguish provider capabilities from delivered Reaktor integration. Publication and inspection consume the authority's retained transitions, not independent dual writes.
Put effecting calls inside awaited step.do operations. Use deterministic step identities from definition/node IDs and revisions, not editable titles or incidental iteration order. Persist compact typed receipts or authorized content references as checkpoint results. In-memory variables and a live socket do not supply recovery state. The provider may retry a step after an external call committed, so each authority must still enforce its own effect protocol. Workflow rules govern provider execution.
Declare retry classification, timeout, overall deadline, durable waits and compensation per operation. Sleeping or waiting for a validated event releases active execution; polling loops and timers in isolate memory do not replace those mechanisms. Human-gate events require authenticated admission, exact tenant/run/gate/revision matching and replay protection. The payload's actor or tenantId is not proof of permission. See retry and sleep behavior and events.
Queue-to-Workflow handoff
Derive a provider-valid instance ID from the scoped logical run key and definition revision. Persist its mapping and input fingerprint at the authority. create({id, params}) rejects an existing retained ID; do not catch every create failure as success. Recover a matching existing instance with get(id) and reconcile status; an unrelated error leaves the Queue item retryable. The current API also offers idempotent createBatch, but skipped existing instances still need mapping/status reconciliation. Verify these APIs against the deployed runtime and bindings. Workers API is the provider reference.
After a confirmed matching durable handoff, the Queue consumer can acknowledge. If the ack is lost, redelivery resolves the same run. Retained instance IDs eventually expire: the application effect ledger must prevent an old redrive from creating a new business effect after provider history is gone. Explicit reruns receive a new run identity and reviewed semantics. Restarting, terminating or deleting a Workflow does not undo effects already committed elsewhere; compensation and cancellation fencing belong to the resource protocol.
Host and shared-code boundary
For BestBuds/Reaktor KMP targets, the Worker entrypoint owns provider bindings and queue/WorkflowEntrypoint hooks. Shared Kotlin code owns envelope validation, operation selection and domain policy. TypeScript can remain the thin host bridge. A browser service worker is a separate execution realm, with its own event lifetime and qualified storage path; it does not supply a Cloudflare executor. Manna's existing TypeScript API can bind its own command handlers directly. Worker and JVM executors expose their actual capabilities instead of promising identical scheduler behavior.
Queue producers/consumers, DLQ and Workflow bindings must be declared for the selected environment, with compatible entrypoint exports. Read the official Queue configuration and Workflow binding configuration. Keep deployment-specific tuning out of portable definitions and record it in the admitted execution profile.
Pub/Sub and Spring execution
Use the existing reaktor-google GCP Pub/Sub profile through Bus for independent subscribers and distribution. Cloudflare publishers use authenticated REST; subscribers require validated push ingress or an explicitly hosted pull consumer. Spring can use a managed pull/push adapter. Validate the signature, expected service account and audience under push authentication, then check current scope and persist admission before successful acknowledgement. Extend pull ack deadlines only for a bounded owned attempt using lease management. Message redelivery resolves the original effect key; the subscription is not a second domain ledger. See the provider's subscription delivery modes.
The selected Spring Work profile uses managed Quartz with persistent JDBC/cluster scheduling plus queue/PubSub adapters. Cron/Quartz reconcile due intent or admit defined schedule occurrences; broker consumers commit effects or confirm matching Workflow handoff before ACK. Restart, duplicate delivery and ambiguous effects use the same authoritative store protocol. Provider scheduling metadata and Workflow history keep their own responsibilities.
Spring distributed workflows use Reaktor's own graph coordinator, with the authoritative run journal owning node outcomes, readiness, joins, waits and recovery. Quartz and brokers supply timing and delivery. Temporal, Restate and Conductor are feature-comparison references, with no adapters or dependencies planned. Cloudflare retains Workflow-owned step history; the two profiles do not race to own the same run.
Adoption across the three applications
| Application | Current source | Queue use | Workflow extension | Authority to preserve |
|---|---|---|---|---|
| Reaktor | Provider inspectors, Service primitives and experimental local Work facade; shared cloud executors are proposed | Outbox relay, bounded projection/repair commands and background dispatch | Export/archive/erase plans, migration orchestration, revisioned graph runs and retained receipts | Dataset's qualified authority and reviewed operator grants |
| Manna | Memgraph records, workspace command/revision protocol, R2 blobs and custom ConnectorQueue Durable Object | Media-derived work, embedding/index updates, notification attempts and connector wakeups | Multi-stage processing, connector reconciliation and Journal document synchronization | Memgraph record versions and workspace authorization; R2 object identity/retention |
| BestBuds / CompanyOS | Existing product delivery services; CompanyOS CompanyOSDagWorkflow uses step.do and human-event waits | Notification/webhook dispatch, media work, projection repair and controlled fanout | Extend the existing DAG runner with real idempotent effects, authority checks, stable steps, cancellation and receipts | Heimdall identity/membership, product database constraints and chat ownership |
Manna's ConnectorQueue is an application DO with persisted tasks and alarms, not Cloudflare Queues. Its media handler currently uses waitUntil(processMedia(...)); adding a Queue or Workflow requires durable admission and recovery rather than renaming that hook. Keep the DO's connector coordination where it earns its role. Manna's Journal rich documents/Google Docs synchronization and Excalidraw diagrams remain product proposals: persist editable content and diagram assets in R2 with record references, revision/conflict policy and lifecycle coverage; a Queue alone does not create bidirectional rich-document sync.
CompanyOS automatic steps currently return completion metadata; that is not proof of an external business effect. Its source step names include titles, and a valid plan can return planned without a Workflow binding. Preserve that distinction in the UI and receipts. Extend this implementation before building a competing DAG runtime, then extract reusable mechanisms when their contracts are qualified.
Evidence and acceptance
Expose intent age, Queue oldest age/backlog, attempts, DLQ count, Workflow/step state, provider failures, source position, projection lag and reconciliation outcomes. Link observations to exact definition/input/authority revisions. Data graph and Operations evidence own the shared representation; avoid loading all payloads and attempts into the graph registry.
Before enabling a real effect, demonstrate: crash after domain commit before publish; publish before relay marking; concurrent duplicate delivery; create success with lost response/ack; step retry after external commit; stale/revoked authority; deletion during processing; quota/rate-limit recovery; and DLQ redrive after provider history expires. Receipts must prove effect outcomes and deletion/cancellation behavior. See data implementation gates for the broader conformance sequence.
Source map
- Reaktor:
reaktor-work,reaktor-service,reaktor-cloudflare; a provider enum or resource inventory is not an executor. - Manna:
targets/api/src/domains/connectors/queue.ts,media.ts, workspace command handling and record sync. - BestBuds:
targets/companyOS/worker/dag-workflow.ts,worker/api.ts,src/core/workflow/dagPlanner.tsand target binding configuration.