How do you catch a step that an asynchronous flow skipped in silence when the final stored record still looks correct?
answer
- The last write hides everything before it
- Some steps leave no mark on the outcome
- Assert each step's own completion marker
- Sent is not the same as handled
- Compare expected and recorded in both directions
basics
~20 sA final-record assertion sees only the last write, so a step whose effect never reaches that record can vanish. Assert instead on the marker each step writes after its own work, and fail when the expected set is incomplete.
solid answer
~50 sAssert positively on each step, not only on the outcome. Many steps in a flow leave nothing behind in the record a case reads at the end - an audit entry, a downstream hand-off, a check meant to gate the write - so skipping one produces exactly the same final state as running it. Under the case's own correlation value, collect the markers the steps recorded once the flow has settled, then compare **both directions**: hops that are expected and absent, and hops that appeared and were not expected. The first catches the silent skip; the second catches a fallback or compensating path running instead of the intended one. Insist that the marker is written by the step *after* its effect, not by the caller when it dispatched the work: a dispatch record survives the receiver never running, which is precisely the case you are hunting.
code
pseudocode · 13 linesexpected = { "risk_check.completed", "ledger.posted", "receipt.queued" }
wait_until(flow_settled(correlation), deadline = 30s)
seen = record_store.hops_for(correlation)
missing = expected - seen
extra = seen - expected
if missing not empty: fail("skipped in silence: " + missing)
if extra not empty: fail("unplanned path ran: " + extra)
# note: "risk_check.dispatched" is written by the caller and
# would still appear if the risk step never ran at allgo deeper
Know the shape of the problem: some steps in a flow leave nothing behind in the record checked at the end, so a case that reads only that record cannot tell whether they ran.
Explain the mechanics of the check: collect the step records written under the case's own value once the flow settles, compare them with the required list, and report the names that are missing.
Demonstrate the judgement an interviewer is listening for: which steps deserve required-hop status, why a dispatch record is not evidence, and how the settle window keeps slow from being reported as skipped.
Own the wider call: which flows justify step-level evidence at all, what it costs the product to record markers the team can trust, and which silent-skip risks are accepted rather than tested.
## Why the end state cannot see a skipped step An assertion on the settled result answers one question: is the system in the state we wanted? That is a good question, and it is blind to an entire class of defect. A flow's steps do not all leave a mark on the record the case reads at the end. Consider a purchase flow: acceptance writes the order, pricing writes the total, a risk check either allows the write or blocks it, an audit entry is appended, a receipt is handed to a downstream sender. If the risk check is silently bypassed - unsubscribed, filtered out, exception swallowed - the order still exists with the right total. The end state is **identical** to a correct run. So is a run where the audit entry was never written, or where the receipt hand-off never happened. This is the failure a correlation trail is worth its cost for. The case is no longer asking "did we land in the right place" but "did the steps we require actually run", and those are different questions with different evidence. | Assertion | Catches | Blind to | |---|---|---| | Settled record has the expected values | wrong output, missing output | a step that changes nothing in that record | | A required hop marker is present | a step silently skipped or unsubscribed | whether that step computed correctly | | No unexpected hop marker is present | a fallback or compensating path that ran | a path that leaves no marker at all | ## Designing the case 1. **Write down the required hops, from the contract.** `expected = {risk_check.completed, ledger.posted, receipt.queued}`. These are steps the flow promises, not steps you observed once. 2. **Wait for the flow to settle, then read.** Before the settle window closes, an absent hop means "not yet" and judging it is a false alarm. After it closes, an absent hop is a finding. 3. **Compare in both directions.** `missing = expected - seen` and `extra = seen - expected`. Asserting only that the required hops are present hides the second half of the story. 4. **Fail with the names.** "risk_check.completed never recorded" is actionable. "flow verification failed" is not. ## The dispatch marker trap The single most common way this technique is defeated is recording the wrong event. A marker written by the caller at the moment it dispatches work - "sent to risk", "published", "enqueued" - proves an **attempt**. It is written whether or not anything ever consumed the work. If the receiving step is unsubscribed, misrouted or quietly discarding what it receives, the dispatch marker still appears, the required set still looks complete, and the case still passes. The very scenario you built the trail for slips through. The rule is: **the marker that carries a verdict is written by the step that did the work, after it did the work.** A dispatch record is useful diagnostically - it narrows the gap to sender or receiver - but it is not evidence that a step ran. ## Absence, arrival and the settle window A skipped step and a slow step look the same for a while: nothing is there. The distinction is entirely a matter of when you look. Give the flow a window justified by how long it normally takes to settle, poll until either the expected set completes or the window closes, and only then treat absence as a defect. Two failure modes come from getting this wrong: - **Judging too early** reports every slow run as a skipped step, and the team learns to ignore the case. - **Judging never** - stretching the window until the case always passes - converts the assertion into a formality. ## Unexpected hops are also signal Comparing only in the "required and present" direction misses the mirror-image defect. A hop that appears and was not expected usually means a path you did not intend ran: a compensating branch that undid part of the work, a fallback the design keeps for failures, a step re-executed after an internal error. Each of those can leave a correct-looking end state while the flow did something quite different from what it promised. Asserting that the recorded set **equals** the expected set - rather than merely contains it - turns those into visible failures instead of invisible ones. ## What the case can honestly say afterwards A case built this way proves that the required, recorded steps ran, in a run identified by the case's own value, within the window the flow is allowed. It does not prove those steps were correct - that is still the job of assertions on the settled outcome - and it says nothing about steps that record nothing at all. Both halves matter: without step-level evidence a silent skip is invisible, and without outcome assertions a complete trail can still ship a wrong answer.
- Why is a marker the caller writes on dispatch weaker evidence than one the step writes itself?A dispatch marker proves an attempt left the caller, not that anything acted on it. If the receiving step is unsubscribed, misrouted or discarding its input, that marker still appears and the case still passes. A marker written by the step after its own effect is absent exactly when the step is skipped, which is the defect being hunted.
- What does a hop that appears but was not in the expected set tell you?Usually that a path you did not intend ran: a compensating branch, a fallback kept for failures, or a step re-executed after an internal error. Any of those can leave a correct-looking end state. Asserting that the recorded set equals the expected set, rather than merely contains it, makes that visible instead of silent.
saying these in an interview costs you the question
- Trusts the final stored record to cover every step
- Counts a dispatch record as proof the step ran
- Checks only that required hops are present
- Calls a hop skipped before the flow has settled
- Treats no thrown error as proof every step ran