skip to content

Should a published stream chain pin the worker its producing work runs on, or leave that choice to each caller?

level: principalimportance: should knowfreq 36%

answer

  1. the inner choice beats the outer one
  2. a pin is a contract, not a convenience
  3. pin producing, never pin delivery
  4. publish which worker delivers values
  5. testing seams argue against pinning

basics

~20 s

Pin only where the work is unsuited to any caller's worker, because a pin nearest the source silently overrides every caller's own switch. Otherwise leave the choice out and publish which worker values are delivered on.

solid answer

~50 s

The decision turns on one mechanical fact: a producing-side switch inside the published chain sits nearer the source than any switch a caller adds outside it, so the subscription crosses the caller's first and the library's last. The library's choice wins, and the caller's looks ignored. That makes pinning a strong, irreversible act of API design, not a convenience. Pin when the producing work is unsuitable for any plausible caller's worker — a long read that would freeze a window — so that correctness does not depend on every call site remembering. Leave it out when the work is cheap or its right home depends on the caller's context, and document the worker values are delivered on so the edge can add its own boundary back. Whatever you choose, make it explicit in the contract: the failure mode of pinning is not wrongness, it is invisibility.

go deeper

for a junior

Take away the mechanical fact: a switch written inside a published chain sits nearer the source than yours, so it wins and your own switch will appear to do nothing.

for a middle

Explain why that happens from the direction of the subscription, and say what a caller can still control — chiefly the final boundary that decides where values are received.

for a senior

Argue the case on a real codebase: which call sites cannot afford the work, which already worked around a pin, and what the contract should state about the delivery worker.

for a principal

Own it as policy: decide when pinning is allowed, forbid pinned delivery in shared code, require the delivery worker in every published contract, and weigh the testing seam a pin removes.

## Why this is a design decision, not a detail A chain published by one layer and subscribed by another carries a hidden asymmetry. The publisher's stages sit **above** the caller's, nearer the source; the caller's switches sit **below**, nearer the subscriber. Because the subscription walks upward, the caller's producing-side switch is crossed first and the publisher's last — so the publisher's choice is the one the source sees. A caller cannot override it by adding their own. That is why pinning is a commitment rather than a default you can revisit at the call site. ## The three positions | Position | What the publisher guarantees | What it costs | |---|---|---| | Pin the producing worker inside the chain | the work never runs on the caller's worker, whoever calls | callers lose the choice entirely; the pinned worker is now part of the contract and hard to change later | | Leave it out | the caller decides, close to the context that knows | every call site must remember; one that forgets freezes its own worker, and the defect shows up in the caller's code | | Pin nothing, but publish the delivery worker | the caller knows where values arrive and can add the one boundary it needs | requires documentation people actually read, and the contract is easy to break silently in a later change | ## How to choose 1. **Ask whether any caller's worker could legitimately run this work.** If the producing work is a long read, no caller's interactive worker can, and every caller would make the same choice. That is the case for pinning: encoding a decision nobody would make differently removes a whole class of defects. 2. **Ask whether the right worker depends on caller context.** Work whose proper home varies — because one caller runs it in a batch with a hundred others and another runs it once from an interactive surface — should not be pinned. A pin would force the batch caller into a worker sized for the interactive case. 3. **Ask what the call site can observe.** Whatever you decide, a caller must be able to find out which worker values arrive on, because a caller at a window edge has exactly one legal worker for its final stage. This is the part most APIs leave unsaid, and it is the part that actually breaks. ## What to standardise across a codebase - **Pin at most once, nearest the source, and say so.** Two pins in a composed chain is a smell: the outer one is doing nothing for the source while paying a hop. - **Never pin delivery deep inside a library.** A forward-only boundary buried in a published chain forces every consumer onto a worker chosen by a layer that does not know what the consumer is. Let the edge add its own boundary back. - **Make the delivery worker part of the published contract**, in the same breath as the value type. A consumer that must paint cannot act on "some worker". - **Decide once how far pinning propagates.** If layer A pins and layer B wraps A, B inherits A's decision whether or not it wanted it. Composition, not configuration, is what makes this decision sticky. ## Evidence to bring, not just preference This is the kind of question where an interviewer is listening for whether you would gather anything before deciding: - How many call sites there are, and how many of them are at an interactive edge that cannot afford the work. - Whether any call site has already worked around the current behaviour — a caller that added its own switch and saw nothing move is direct evidence that something upstream is already pinning. - Whether subscriptions are frequent, since every surplus switch costs a handoff during setup and a hot path amplifies it. - Whether tests must control the worker. A pinned worker makes deterministic tests harder, and a testing seam is a legitimate reason to leave the choice out even when correctness argues for pinning. ## The position worth defending A defensible answer usually lands in the middle: pin only where the producing work is categorically unsuited to a caller's worker, never pin delivery, and publish the delivery worker as part of the contract. The reasoning matters more than the verdict — an interviewer is checking that you know a pin silently wins over every caller's later attempt, and that you would rather make the decision visible than make it convenient.

  • Why is pinning the delivery worker inside a published chain worse than pinning the producing worker?
    Because the right delivery worker is a property of the consumer, not the producer. A library cannot know whether its values end up painting a window or feeding a batch job, and its boundary costs every consumer a hop while forcing the wrong one on some of them.
  • What evidence would tell you a published chain is already pinning its producing worker?
    A caller that added its own producing-side switch and observed nothing move. The caller's switch is further from the source, so the inner pin wins and the outer one looks ignored — that symptom is close to conclusive.
  • How does pinning affect testability?
    It removes a seam. A test that wants deterministic, single-worker execution can no longer choose it from outside, because the inner switch wins. That is a real argument for leaving the choice out even where correctness leans toward pinning.

saying these in an interview costs you the question

  • Assumes a caller can always override a chain's pinned worker
  • Pins the delivery worker inside a shared library
  • Treats the delivery worker as an implementation detail not worth documenting
  • Adds a second pin instead of removing the first
  • Decides from preference with no count of call sites
  • Ignores that pinning removes a seam tests relied on