Which observable do you assert on so that a redelivered stock-adjustment message being applied twice would actually fail the case?
answer
- A green pass can prove nothing
- Some effects absorb a second apply
- Counts and balances move; flags do not
- Pick the effect nearest the harm
- Watch the assertion go red once
basics
~20 sAssert on an effect that accumulates — appended ledger rows, a balance, a revision counter, outbound notifications sent — because a second application moves it. Status flags and repeated overwrites absorb the second application and pass whatever the consumer does.
solid answer
~50 sSeparate effects into two families. **Absorbing** effects are idempotent by construction: a status set to a fixed value, a whole-record overwrite with the same fields, adding an identifier to a set. A second application leaves them identical, so asserting on them passes whether the guard works, is missing, or was never exercised. **Accumulating** effects move every time the handler runs: appended ledger rows, a balance or stock level, a revision counter, outbound notifications sent. Assert on at least one of those, captured as a delta from a baseline, and prefer the one nearest the real harm — money moved twice, or a second message to the same recipient. When the only business outcome is a flag, drop a layer and use the record's revision, the audit rows the write appends, or a count of outbound messages. Then prove it discriminates by watching it fail against a doubled application.
code
pseudocode · 10 lines# absorbing - reads the same whether applied once or twice
assert order.status == "shipped"
assert order.shippedAt != null
assert order.tags contains "dispatched"
# accumulating - a second application moves every one of these
assert count(ledgerEntries where orderId = "o-4471") == entriesBefore + 1
assert order.revision == revisionBefore + 1
assert notificationsSent(orderId = "o-4471") == notificationsBefore + 1
assert stockOnHand == stockBefore - 1go deeper
Be ready to explain that some checks pass no matter what the consumer did — setting an already-set flag changes nothing — so the value you assert on decides whether the case is capable of catching anything.
Explain the two families with examples: absorbing effects such as a fixed status or a set membership, and accumulating effects such as appended rows, balances, revision counters and outbound notifications.
Show the judgment: pick the accumulating effect closest to the real harm, assert every downstream a duplicate would double, use deltas from a baseline, and confirm the assertion goes red against a doubled application.
Own the wider point that an assertion incapable of failing is a liability across a whole suite, and be able to describe how you would find and retire the ones already accumulating in yours.
## Two families of effect Every effect a consumer produces falls into one of two families, and only one of them can serve as the oracle for a replay case. | Effect the handler produces | What a second application does to it | Usable as the oracle? | | --- | --- | --- | | Status field set to a fixed value | Nothing — it is already that value | No | | Whole-record overwrite with the same fields | Nothing — the same bytes land again | No | | Adding an identifier to a set | Nothing — it is already a member | No | | Appending a ledger or audit row | A second row appears | Yes | | Moving a balance or decrementing stock | It moves twice | Yes | | Incrementing a revision or version counter | It advances twice | Yes | | Emitting an outbound notification or event | A second one goes out | Yes | The absorbing family is idempotent *by construction*: the write is the same operation whether it runs once or a hundred times. Asserting on it tells you nothing about whether the consumer recognised the duplicate, because the outcome is identical in both worlds. ## Why an absorbing assertion is worse than having no case A case asserting `order.status == "shipped"` after a replay passes when the guard works, passes when the guard is missing, and passes when the second copy was never even consumed. It is a green light wired to nothing. That is worse than an absent case, because the suite now carries standing evidence for a property nobody actually checked, and the next person to touch the consumer trusts it. The single most useful question to ask of any replay assertion is: **what would this value read if the message had been applied twice?** If the answer is "the same thing", the assertion is decoration. ## Choose the observable nearest the harm When more than one accumulating effect exists, pick the one whose doubling is the actual damage, because that is the one a reader will care about when it goes red: - **Money and inventory** — a balance moved twice, stock decremented twice, a payout duplicated. - **Customer-visible messages** — a second confirmation email or push to the same recipient is the duplicate people report, and it is frequently the effect the guard forgot. - **Events published downstream** — one message in, two events out, and every consumer downstream inherits the duplicate. - **Calls to a paid or rate-limited external interface** — counted at the receiver the run controls. Assert on more than one when the handler has several effects: guards commonly protect the primary write and leave the notification unprotected, so the record is correct and the customer is annoyed. ## When everything visible absorbs Sometimes the business outcome really is a flag. You are not stuck; you are looking one layer too high. Reach for something the write itself accumulates: - the record's **revision or version counter**, which advances on every write even when the field values are unchanged; - **audit or history rows** appended by the write path; - a **count of outbound messages** captured at whatever receiver the case stands up; - a **handled-count** the consumer already exposes, which distinguishes "handled twice, applied once" from "handled once". And be honest about the remaining case: if literally nothing accumulates anywhere, the operation is idempotent by construction, there is no defect available to find, and the right answer is to record that reasoning rather than to ship a case that cannot fail. ## Baselines and negative controls 1. **Capture before, assert a delta.** `entriesAfter == entriesBefore + 1` survives leftover data and other cases writing to the same deployed target; `entriesAfter == 1` does not, and a fixed expected total can even coincide with a double application on a dirty target. 2. **Prove the observable discriminates.** Run the case once against a build whose duplicate guard is removed, or apply the effect a second time by hand, and confirm the assertion goes red. Until you have seen it fail, you have not established that it can. 3. **Keep the check cheap and repeat it.** Re-running the negative control whenever the handler's effects change is what stops the assertion silently drifting onto an absorbing field during a later refactor. 4. **Name the observable in the failure output.** "Expected one ledger entry for this payment identity, found two" is a diagnosis; "assertion failed" sends the next reader back to the code.
- The only business outcome of the message is a status flag. What do you assert instead?Look one layer below the business outcome: the record's revision or version counter, audit rows appended by the write path, a count of outbound messages captured at a receiver the case controls, or a handled-count the consumer exposes. If genuinely nothing accumulates anywhere, the operation is idempotent by construction — record that reasoning rather than shipping a case that cannot fail.
- Why is asserting a fixed expected total weaker than asserting a delta from a captured baseline?A fixed total assumes the starting state, so leftover data or another case writing to the same deployed target flips the verdict for reasons unrelated to duplicates — and a double application can even land on the number you expected. Capturing before and asserting the difference isolates the effect of this message from everything else in the target.
- The consumer guards its database write but sends its notification unguarded. Which assertion catches that?Only one counting the outbound notifications for that recipient. A case asserting a single row passes happily while the customer receives two messages, which is usually the duplicate people actually report. Assert on every downstream effect the message produces, not just the primary write.
Asserting on a flag after a replay is like weighing a truck on a scale that stops at one tonne: the reading is the same whether one load or two went on.
saying these in an interview costs you the question
- Asserts a status flag and calls the consumer idempotent
- Treats the second delivery raising no error as the pass condition
- Checks only that the record still exists after the replay
- Uses absolute expected totals instead of a delta from a baseline
- Never verifies the assertion fails when the effect is doubled
- Asserts the primary write only and ignores outbound notifications