Correlate Distributed Multi-Domain Services with stackId and namespace
In modern microservice architectures, an end-to-end business transaction rarely lives inside a single service. An Order Service might initiate a checkout workflow, but midway through execution it needs to invoke an independent Fulfillment or Payment Service via Kafka or HTTP REST.
Traditionally, tracking this distributed flow across microservices requires deploying heavy external orchestrator clusters (like Temporal or Camunda) or stitching together fragmented distributed traces.
Siglo provides a zero-daemon alternative using two first-class options in ExecutionOptions:
stackId: An explicit execution stack identifier passed downstream across service boundaries.namespace: A multi-tenant partition key (e.g.,tenant_acme_retail) that scopes storage, idempotency, and live monitoring telemetry.
Architecture: Parent-Child Correlated Workflows
Instead of forcing multiple distinct services to share the exact samestackId—which would collapse their distinct DAG graphs into a single AST and relegate downstream steps into “Other observed steps”—the recommended pattern is Parent-Child Correlated Workflows:
- Service A (Order Domain) executes with its own
stackId(e.g.stack-acme-order-101). - In its dispatch step (
order:dispatchToFulfillment), it forwards a correlated child stack ID (e.g.stack-acme-order-101:fulfillment), together withx-parent-stack-idandx-tenant-id. - Service B (Fulfillment Domain) runs its workflow using the child
stackId. - In the Live Monitoring Dashboard:
- Both services receive their own complete, fully-connected DAG topologies.
- Searching for the parent stack ID (
stack-acme-order-101) instantly surfaces both parent and child runs in the Run List. - The trigger step in Order Service records and references the child workflow execution.
1. The Downstream Service: Fulfillment Domain
The downstream service exposes an independent workflow responsible for inventory, payment, and shipping. It acceptsx-stack-id and x-tenant-id in its HTTP request headers and runs its workflow:
2. The Upstream Service: Order Domain
In the Order Service, the workflow initiates the business process. During the dispatch step, it extracts$stackId() and $namespace(), generates a correlated child stack ID (${stackId}:fulfillment), and forwards them in the HTTP headers:
3. How Live Monitoring Displays Parent & Child Workflows
When both services emit events to the shared Live Monitoring instance:- Separate, Complete Connected DAGs:
order-processing-service(stack-acme-order-101) renders its full 4-step Order graph.fulfillment-service(stack-acme-order-101:fulfillment) renders its full 4-step Fulfillment graph.- No steps are dumped into “Other observed steps” because each service publishes its own complete AST.
- Correlated Search by Prefix:
- Typing
stack-acme-order-101in the dashboard search bar matches and displays both the parent order workflow and the child fulfillment workflow in the Run List.
- Typing
- Trigger Causality in Step Details:
- Clicking into
order:dispatchToFulfillmentin the Order graph reveals thechildWorkflowobject with the exact childstackId, providing clear bidirectional traceability.
- Clicking into
- Multi-Tenant Filtering:
- The Tenant dropdown filters all executions to
tenant_acme_retail, displaying both the parent and child workflows for that tenant.
- The Tenant dropdown filters all executions to
4. Run the Example via Docker Compose
The complete runnable example is available inexamples/distributed-cross-service-workflows/.
Service Ports
Step 1: Start the System
From the repository root:Step 2: Dispatch Sample Orders
Run the included smoke test script:curl:
Step 3: Inspect Live in the Dashboard
- Open
http://127.0.0.1:4200in your browser. - Select
tenant_acme_retailortenant_globex_corpin the tenant dropdown. - Type
stack-acme-order-101in the search bar to see both:order-processing-service(stack-acme-order-101)fulfillment-service(stack-acme-order-101:fulfillment)
- Click
order-processing-serviceto inspect its connected Order graph and clickorder:dispatchToFulfillmentto see the child link. - Click
fulfillment-serviceto inspect its connected Fulfillment graph.
Step 4: Stop the System
5. Direct Host Workflow (Without Docker)
You can also run the complete demo directly with Node:Key Best Practices
- Use Correlated Hierarchical Stack IDs:
Naming child workflows with
${parentStackId}:<domain>preserves full AST graph connectivity for both workflows and ensures they appear together when searching by parent ID. - Propagate Tenant Namespace:
Passing
namespacemaintains tenant-level metrics, storage isolation, and idempotency scoping across microservice boundaries. - Record Child Workflow in Step Output:
Returning
{ childWorkflow: { stackId: childStackId, service } }from the dispatch step gives operators immediate drill-down links in the step inspection drawer.
