skip to content

A detail pane loads whichever queue item is highlighted: what breaks if those loads are merged instead of switched to the newest?

level: seniorimportance: should knowfreq 55%

answer

  1. last to finish wins the pane
  2. a stale result overwrites the fresh one
  3. one highlight, one live load
  4. cancel on the newer element
  5. cancellation must reach the call

basics

~20 s

Merging leaves every earlier load in flight, so whichever finishes last wins the pane: a stale load can overwrite the highlighted item's data. Switch-to-newest cancels the in-flight load on each highlight change, leaving at most one alive.

solid answer

~50 s

Merging keeps every load alive, and each one writes to the pane when it completes. Because completion order follows latency rather than highlight order, a slow load for an item the user has already moved off can finish last and overwrite the correct data - a last-write-wins race that only appears when latencies differ, which is why it survives testing. Switching to the newest cancels the in-flight inner source the moment a new highlight arrives, so at most one load is ever alive and its result necessarily belongs to the current highlight. Two caveats: the cancellation is only as real as the inner source makes it, since a source that ignores the signal stops delivering but leaves the call running; and any effect inside a cancelled load may be half-done, which is why switching suits reads and not writes.

code

pseudocode · 9 lines
pseudocode
current = none

for each highlight in highlights:
    if current is not none:
        cancel(current)          // abandon the load still in flight
    current = subscribe(load(highlight), on_result = function(detail) {
        show(detail)             // only the surviving load can reach here
        current = none
    })

go deeper

for a junior

Recall the symptom and its name: with merging, the pane ends up showing whichever load finished last, which need not be the item currently highlighted.

for a middle

Explain why completion order diverges from highlight order under merging, and that switching to the newest holds at most one inner subscription by cancelling the previous one when an element arrives.

for a senior

Show the production judgment: reproduce it with deliberately unequal latencies, check that the inner source actually propagates cancellation, and say why the strategy suits abandonable reads rather than writes.

for a principal

The angle to own is that a sequence carrying user intent supersedes itself by nature, so the default strategy for intent-driven pipelines is a standard worth setting once rather than re-arguing per screen.

## The race The pane is driven by a sequence of highlight changes. Each change is mapped to a load of that item's detail, which is an asynchronous call, so a flattening strategy has to be chosen. Choose merging and the step keeps **every** load alive. Each load, when it completes, renders into the pane. Now make latencies differ, which is the normal condition in production: 1. The user highlights item A. Its load begins and will take 1200 ms, because that record is cold. 2. Two hundred milliseconds later the user highlights item B. Its load begins and takes 80 ms. 3. B renders. The pane is correct. 4. Nine hundred milliseconds later A completes and renders. **The pane now shows A's data while B is highlighted.** Nothing threw. No log line was written. The user sees a pane that disagrees with the selection, usually blamed on caching. This is **last-write-wins**: with merging, the winner is whichever call was slowest, and slowness is exactly what you cannot control. ## What switching does instead A switch-to-newest strategy holds at most one inner subscription. When a new element arrives at the step, it **cancels the current inner subscription first**, then subscribes to the new one. Two properties follow: - **Whatever renders belongs to the current highlight**, because no older load is alive to render. - **Superseded work is abandoned**, so a user scrolling through ten items issues up to ten loads but keeps at most one - and if cancellation is propagated, most of those calls never finish, which also reduces load on the dependency. The ordering problem disappears not because results were sorted but because the losing results were never produced. ## For a highlight-driven pane, the four strategies rank clearly | strategy | what the pane shows | superseded work | fit here | |---|---|---|---| | bounded concurrent merge | whichever load finished last | all of it completes | wrong: stale overwrite | | sequential concatenation | every item in turn, ending correct | all of it completes | wasteful, and lags behind the user | | switch to newest | the highlighted item | cancelled | right for a read-only pane | | ignore while busy | the item highlighted when idle | never started | wrong: ignores the user's newest action | Sequential concatenation deserves a note, because it is the trap answer. It does eventually converge on the right item, since the last load in the chain is the newest highlight, but it renders every intermediate item on the way and the pane visibly lags by the sum of the queued latencies. ## Cancellation is only as real as the inner source Cancelling an inner subscription is a signal travelling from the flattening step to the source it subscribed to. It reliably stops **delivery** - nothing more arrives from that source. Whether it stops the **work** depends on whether the inner source propagates the signal down into the call it owns: releasing the connection, abandoning the request, stopping the loop it was running. An inner source that ignores the signal gives you a correct pane and unchanged load on the dependency, which is a fix half done. This matters more where the inner work is not a read: - A cancelled load that only read data leaves nothing behind. - A cancelled call that had begun a write may leave partial state, and nobody is waiting on its result to notice. - A cancelled call whose result had to be recorded - an audit entry, a billing event - loses that record silently. So the honest rule is: switch to the newest when the inner work is a **read that can be abandoned**, and reach for ignore-while-busy or sequential concatenation when the inner work must run to completion. ## Proving it, and preventing it The defect is trivially reproducible once you stop assuming uniform latency: delay the first load far more than the second, change the highlight while the first is in flight, and assert which data the pane ends up holding. Under merging the pane holds the first item's data; under switching the first result never arrives at all. A test that stubs both loads to return immediately passes under either strategy and proves nothing. In a review, the signal to look for is a flattening step whose upstream is **user intent** - a highlight, a search box, a filter, a tab. Intent supersedes itself by nature: only the latest one is still wanted. Whenever the upstream sequence has that character and the inner work is a read, merging is the wrong strategy and the argument is finished.

  • The strategy cancels the previous load, yet the outbound call still completes - why?
    Cancellation is a signal travelling up the inner subscription. It stops delivery immediately, but the underlying work stops only if the inner source propagates it - closing the connection or abandoning the request. A source that merely stops emitting gives you a correct pane and unchanged load on the dependency.
  • When is switching to the newest the wrong choice here?
    When the inner work has effects that must finish - a write, a charge, an audit record - because cancelling mid-flight leaves partial state nobody is watching. When every element's result must be recorded, use ignore-while-busy or sequential concatenation and accept the added latency.
  • How would you reproduce the defect deliberately?
    Make the inner latencies differ: delay the first load far longer than the second, change the highlight while the first is in flight, then assert which data the pane holds. Under merging it holds the first item's; under switching the first result never arrives. Equal stub latencies prove nothing.

A waiter halfway to the kitchen with one table's order turns straight back the moment that table changes its mind, so only the latest order is ever cooked. Merging is the waiter who places both orders and serves whichever the kitchen happens to finish last.

saying these in an interview costs you the question

  • Thinks the newest load always finishes last, so merging is safe
  • Believes cancelling a subscription always stops the outbound call
  • Uses switch-to-newest for inner work whose effects must complete
  • Assumes the defect shows up in tests where every load is instant
  • Thinks switching drops the newest element while an older call runs
  • Blames the dependency's latency rather than the flattening strategy