| Workflow Client | Owns client protocol, request identity, retry, and resume behavior. In this design it participates in: Persist workflow-start event and enqueue one deterministic decision task. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents the external caller from also owning the contract and failure behavior of Workflow API. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Worker code becomes nondeterministic” to the external caller. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Workflow Client boundary before extracting or scaling it. |
| Workflow API | Owns authentication, validation, quotas, deadlines, and routing. In this design it participates in: Executor replays history, runs pure workflow code, and appends commands as events. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Workflow Client from also owning the contract and failure behavior of Namespace / Quota. | Put protocol, authentication, quotas, and business transitions in one process. Acceptable at low scale, but it couples external traffic risk to domain releases. Here that simpler choice would couple “Activity succeeds after timeout” to Workflow Client. | Costs another hop, policy distribution, and a high-blast-radius fleet. Introduce it when many clients or services need one protocol and protection boundary. Measure the latency, saturation, lag, or mismatch at the Workflow API boundary before extracting or scaling it. |
| Namespace / Quota | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Dispatch activities with stable IDs, retries, heartbeats, and independent queues. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Workflow API from also owning the contract and failure behavior of History Store. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Timer fires twice” to Workflow API. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Namespace / Quota boundary before extracting or scaling it. |
| History Store | Owns authoritative versioned state or immutable evidence. In this design it participates in: Timers/signals append durable events and wake a new workflow decision. | Defines the source of truth and commit boundary. It prevents Namespace / Quota from also owning the contract and failure behavior of Workflow Task Queue. | Let each service persist its own interpretation. That removes one clear commit boundary and makes retries, support, and reconciliation ambiguous. Here that simpler choice would couple “History grows beyond replay budget” to Namespace / Quota. | Costs schema migration, replication, backup, and shard ownership. Split storage only when access patterns, retention, or compliance boundaries materially differ. Measure the latency, saturation, lag, or mismatch at the History Store boundary before extracting or scaling it. |
| Workflow Task Queue | Preserves durable ordering, replay, and consumer checkpoints. In this design it participates in: Compact/archive closed histories and support versioned code routing or operator reset. | Decouples bursts and failure from user acknowledgment. It prevents History Store from also owning the contract and failure behavior of Deterministic Executor. | Call every downstream consumer synchronously. That couples user latency and availability to analytics, notification, indexing, and audit dependencies. Here that simpler choice would couple “Deployment removes old workflow version” to History Store. | Costs eventual consistency, schema evolution, replay tooling, idempotent consumers, and lag operations. Earn it when bursts or downstream failure must not block acknowledgment. Measure the latency, saturation, lag, or mismatch at the Workflow Task Queue boundary before extracting or scaling it. |
| Deterministic Executor | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Persist workflow-start event and enqueue one deterministic decision task. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Workflow Task Queue from also owning the contract and failure behavior of Activity Queues. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Worker code becomes nondeterministic” to Workflow Task Queue. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Deterministic Executor boundary before extracting or scaling it. |
| Activity Queues | Preserves durable ordering, replay, and consumer checkpoints. In this design it participates in: Executor replays history, runs pure workflow code, and appends commands as events. | Decouples bursts and failure from user acknowledgment. It prevents Deterministic Executor from also owning the contract and failure behavior of Activity Workers. | Call every downstream consumer synchronously. That couples user latency and availability to analytics, notification, indexing, and audit dependencies. Here that simpler choice would couple “Activity succeeds after timeout” to Deterministic Executor. | Costs eventual consistency, schema evolution, replay tooling, idempotent consumers, and lag operations. Earn it when bursts or downstream failure must not block acknowledgment. Measure the latency, saturation, lag, or mismatch at the Activity Queues boundary before extracting or scaling it. |
| Activity Workers | Executes idempotent asynchronous work under lease and retry policy. In this design it participates in: Dispatch activities with stable IDs, retries, heartbeats, and independent queues. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Activity Queues from also owning the contract and failure behavior of Timer Wheel. | Perform the work before acknowledging the caller. This gives simpler consistency but unbounded tail latency and fragile retries. Here that simpler choice would couple “Timer fires twice” to Activity Queues. | Costs leases, checkpoints, retries, DLQs, and lag operations. Separate once execution time or burstiness no longer fits the request deadline. Measure the latency, saturation, lag, or mismatch at the Activity Workers boundary before extracting or scaling it. |
| Timer Wheel | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Timers/signals append durable events and wake a new workflow decision. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Activity Workers from also owning the contract and failure behavior of Signal Ingest. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “History grows beyond replay budget” to Activity Workers. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Timer Wheel boundary before extracting or scaling it. |
| Signal Ingest | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Compact/archive closed histories and support versioned code routing or operator reset. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Timer Wheel from also owning the contract and failure behavior of Visibility Index. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Deployment removes old workflow version” to Timer Wheel. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Signal Ingest boundary before extracting or scaling it. |
| Visibility Index | Serves a low-latency, disposable projection with authoritative fallback. In this design it participates in: Persist workflow-start event and enqueue one deterministic decision task. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Signal Ingest from also owning the contract and failure behavior of Retry / DLQ. | Read authoritative storage for every request. Simpler initially, but latency and source-of-truth load scale together and a hot key becomes a database incident. Here that simpler choice would couple “Worker code becomes nondeterministic” to Signal Ingest. | Costs invalidation, staleness, stampede protection, and memory. Add or split it only after the workload (100M active workflows · years-long history · deterministic replay) proves repeated reads dominate. Measure the latency, saturation, lag, or mismatch at the Visibility Index boundary before extracting or scaling it. |
| Retry / DLQ | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Executor replays history, runs pure workflow code, and appends commands as events. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Visibility Index from also owning the contract and failure behavior of Versioning Router. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Activity succeeds after timeout” to Visibility Index. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Retry / DLQ boundary before extracting or scaling it. |
| Versioning Router | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Dispatch activities with stable IDs, retries, heartbeats, and independent queues. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Retry / DLQ from also owning the contract and failure behavior of Archival Store. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Timer fires twice” to Retry / DLQ. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Versioning Router boundary before extracting or scaling it. |
| Archival Store | Owns authoritative versioned state or immutable evidence. In this design it participates in: Timers/signals append durable events and wake a new workflow decision. | Defines the source of truth and commit boundary. It prevents Versioning Router from also owning the contract and failure behavior of Operations / Reset. | Let each service persist its own interpretation. That removes one clear commit boundary and makes retries, support, and reconciliation ambiguous. Here that simpler choice would couple “History grows beyond replay budget” to Versioning Router. | Costs schema migration, replication, backup, and shard ownership. Split storage only when access patterns, retention, or compliance boundaries materially differ. Measure the latency, saturation, lag, or mismatch at the Archival Store boundary before extracting or scaling it. |
| Operations / Reset | Owns one bounded domain decision, transition, or operational capability. In this design it participates in: Compact/archive closed histories and support versioned code routing or operator reset. | Separates a distinct scale, ownership, policy, or failure boundary. It prevents Archival Store from also owning the contract and failure behavior of operators and repair tooling. | Keep this behavior inside an adjacent service. Prefer that simpler option until independent scale, ownership, policy, or failure isolation is measurable. Here that simpler choice would couple “Deployment removes old workflow version” to Archival Store. | Costs an interface, deployment, telemetry, ownership, and failure mode. Keep it in-process first; extract when independent scale or reliability pays for the boundary. Measure the latency, saturation, lag, or mismatch at the Operations / Reset boundary before extracting or scaling it. |