- A supplier launches a catalogue import.
- The dashboard says the import is still running.
- We faced this observability problem while building a procurement marketplace on Medusa.
- We added a tracking contract that gives the business operation one stable identity, carries its ancestry into nested work and projects the resulting execution tree into an operator-readable
The client problem
A supplier launches a catalogue import. The main operation stages the file, creates products and starts follow-on work for categorisation, images and search.
The dashboard says the import is still running. The logs contain dozens of workflow executions. Some have random identifiers, some mention the HTTP request and others refer to a child job. Nothing clearly answers the merchant's question: what happened to my import?
We faced this observability problem while building a procurement marketplace on Medusa. Long-running commerce operations did not remain one flat workflow. They became families of parent workflows, nested workflows and individual steps spread across server and worker processes.
We added a tracking contract that gives the business operation one stable identity, carries its ancestry into nested work and projects the resulting execution tree into an operator-readable monitor.
The goal was not more logs. It was one coherent story from the supplier's action to the step that now needs attention.
The client sees one operation, not a collection of workflows
From the supplier's perspective, there is one action: import this catalogue.
Inside the platform, that action may involve file staging, row validation, product writes, price updates, inventory relationships, image localisation and search synchronisation. Each capability can have its own lifecycle because it has different scaling and recovery needs.
That decomposition is useful until an operator has to investigate it.
If every workflow creates an unrelated identifier, the operational view mirrors the implementation rather than the client's journey. Support can find five successful jobs and one failed job without knowing whether they belong to the same import. A retry may appear as an entirely new event. A child workflow can look healthy while its parent remains blocked.
We therefore start from a simple rule: the business operation owns the root identity. Technical execution may branch, but it must not lose the operation it serves.
Give the operation an identity before launching work
For catalogue imports, the platform creates a durable import record before starting the workflow. Its ID becomes the transaction identity supplied to Medusa's workflow engine.
That order matters.
If the workflow engine invents the only useful identifier after launch, the API, database and interface all need to discover and copy it correctly. If the business record exists first, the acknowledgement, status endpoint, workflow and operator view can share one reference from the beginning.
The same pattern applies beyond imports. A reindex job, bulk publication job or media-localisation run can reserve its identity as part of accepting the business request, then use that reference when orchestration begins.
A stable identity gives support a precise sentence: “Import X is waiting in image processing.” It also gives code a join key that does not depend on matching approximate timestamps or parsing log messages.
The ID is not merely for debugging. It is part of the product contract returned to the caller.
Record why and where the workflow started
An identifier alone does not explain an execution.
Our tracking wrapper attaches a small context to every root run. It records the workflow, transaction, execution mode and source that launched it. When request context exists, it can also carry the request and authorised actor. Host and process information help distinguish where execution was observed in a server-worker deployment.
The source is especially useful. The same workflow may be launched by a supplier route, an administrative recovery action or a scheduled reconciler. The workflow name says what code is running; the source says why this run exists.
This context is deliberately structured rather than hidden in prose logs. Operators can filter it. A monitor can group by transaction. Tests can verify that nested work inherits the correct root.
We avoid turning the context into a data dump. It should contain identifiers and operational dimensions, not arbitrary request bodies or secrets. Observability becomes less useful when the safe fields are buried inside everything the application happened to know.
Carry parent and root identity into nested workflows
A nested workflow needs two relationships.
The parent answers: which execution launched me directly? The root answers: which original business operation does this entire branch serve?
They are not interchangeable.
Imagine catalogue import A starts image batch B, which starts localisation run C. C's parent is B, but its root remains A. An operator looking at C should be able to move one level upward to B or all the way back to the supplier's import.
The nested tracking context we built carries the parent workflow ID, parent transaction ID, inherited root transaction ID and, where available, the parent run ID. If no earlier root exists, the parent's transaction becomes the root.
This creates a family tree without forcing every workflow into one giant orchestration definition. Teams can keep capabilities independently recoverable while preserving the client journey that connects them.
Keep workflow steps visible inside each branch
The family tree tells an operator which workflow owns the problem. The step timeline explains what that workflow was doing.
Our monitor projection includes the execution state, update time, duration, number of steps, number completed and counts by step state. A detail view can then expose the relevant step sequence.
This distinction prevents a common support failure. “The workflow is running” is not enough if its last useful step completed forty minutes ago. A freshness signal and step state can show whether work is actively advancing, waiting, compensating or stale.
The language still needs interpretation. A technical step named after an internal function may be accurate and useless to an operator. Workflow and step names should make the business phase recognisable, while the interface can translate deeper implementation detail into a concise status.
The monitor is not a replacement for domain progress. It complements the import session or job record: domain state explains the merchant outcome; workflow state explains execution.
Persist a queryable projection instead of scraping logs
Console logs are valuable for detailed diagnosis, but they are a weak primary interface for commerce operations.
They may live in another service, rotate quickly or contain several workers interleaved. Searching them requires access and technical knowledge. Parent-child relationships exist only if every message formats them consistently.
We persist the tracking context into Medusa's workflow execution and also maintain an operator-oriented execution-log projection. The projection can be filtered by workflow, transaction, source, parent, root, actor, host, state and freshness.
That lets an operator begin with the known business ID and retrieve the relevant family rather than scanning the entire application history.
Projection is the important word. The monitor organises execution evidence; it does not become the canonical source for orders, imports or products. If the projection is delayed, the business record still owns the outcome. Reconciliation can refresh the view from the workflow engine's stored execution data.
This ownership boundary keeps observability useful without letting it redefine commerce truth.
Distinguish a tracking gap from a business failure
Tracking is infrastructure too, and it can fail.
After launching a workflow, the wrapper attempts to persist the structured context and snapshot the execution log. It retries bounded races where the engine's execution row may not yet be visible. If post-launch tracking still fails, the application logs a warning.
That warning is not automatically evidence that the business workflow failed. The run may be advancing while its operator projection is incomplete.
Conflating those states creates dangerous recovery. An operator might restart a healthy import because the monitor missed a row, producing duplicate work. Conversely, a perfect tracking record does not prove the business outcome was correct.
We treat observability health and operation health as related but distinct. The monitor should reveal when its own information is stale or partial. Recovery can refresh the projection before deciding that the underlying workflow needs intervention.
Honest observability includes uncertainty about observability itself.
Make stale work visible, not merely old
Age alone is ambiguous. A completed workflow from yesterday is old and healthy. An active workflow with no update for an unexpected interval may need attention.
The monitor projection calculates last-update age and a stale signal alongside execution state. Operators can filter active and stale runs rather than sorting an endless chronology.
The domain matters when choosing the threshold. A ten-minute pause could be normal for an external batch and suspicious for a four-step internal diagnostic. The monitor should provide the evidence; the capability-specific policy decides when it becomes an incident.
This is where the execution tree becomes commercially useful. A stale image child can explain why a product import appears incomplete even though its catalogue-write parent succeeded. The operator can focus recovery on the affected branch instead of replaying the entire import.
Prioritisation follows the client's blocked outcome, not the number of red log lines.
Build an investigation path for operators
A useful workflow monitor should support a short investigation:
- Start with the transaction ID shown to the supplier or stored on the business job.
- Open the root execution and confirm its business source and current state.
- Inspect direct children and identify which branch remains active, failed or stale.
- Read the branch's step timeline and last meaningful update.
- Compare workflow execution with the canonical import, product or projection state.
- Decide whether to wait, refresh observability, retry a safe phase or run reconciliation.
This sequence is more valuable than a dashboard filled with global workflow counts. It moves from the client's question to a bounded technical decision.
We also keep filters for workflow and source so engineering can investigate recurring patterns across operations. But the primary route remains business ID to execution family to actionable branch.
Avoid three misleading observability shortcuts
First, do not use the HTTP request ID as the only identity. It explains admission, not the background lifecycle that follows.
Second, do not flatten every nested run into one status. A root can have completed its responsibility while a follow-on capability continues independently. Preserve the tree and define the business completion boundary explicitly.
Third, do not treat the number of children returned on one paginated query as the global family size. A UI can count relationships among the rows it currently holds, but a complete family needs a query scoped by the root identity.
These details sound technical, yet they directly affect trust. An incomplete monitor that presents estimates as complete facts can send operators toward the wrong recovery action.
A practical workflow-tracking checklist
Before launching long-running Medusa work, ask:
- Does a durable business record exist before orchestration starts?
- Is its ID used as the stable transaction identity?
- Does the API return that identity to the caller?
- Is the launch source recorded?
- Can actor and request context be attached without exposing sensitive payloads?
- Does every nested workflow carry direct-parent and root identities?
- Are step states and last-update time queryable?
- Can operators filter by transaction, source, state and stale status?
- Is the monitor clearly a projection rather than business truth?
- Can a tracking failure be distinguished from a workflow failure?
- Can the team navigate from the client's operation to the exact branch needing recovery?
If the answer depends on manually comparing timestamps across log files, the operation is not yet observable enough for the people responsible for it.
Why this matters beyond debugging
Medusa gave us composable workflows, which allowed the marketplace to separate imports, media, search and other capabilities according to their own operational needs.
We added the connective tissue: stable business transaction IDs, structured launch context, parent-root ancestry, durable execution projection and an operator investigation path.
The result is not one enormous workflow. It is a set of focused workflows that still read as one client story.
That is the architectural advantage we wanted. Extensibility lets the platform grow; traceable ancestry keeps that growth understandable. When a merchant asks what happened to an import, the answer should begin with their operation and end at the precise step requiring attention—not with a search through unrelated logs.
