skip to content

A chat screen builds a message stream but no request is sent — what act starts the work, and what does it return?

level: juniorimportance: must knowfreq 72%

answer

  1. description, not work
  2. nothing runs until something asks
  3. subscribing wires and starts
  4. the call hands back a handle
  5. no handle, no cancel

basics

~20 s

Subscribing starts the work; building a stream only describes it. A subscription call attaches a subscriber to the source, triggers whatever the source does to produce values, and hands back a handle the caller uses to cancel that run.

solid answer

~40 s

Chaining stages together produces a *description* of work — an object that knows how to open the connection and transform each message, but has opened nothing. The description becomes a running sequence only when a subscriber attaches to it. That act wires the chain from subscriber up to source, starts whatever the source does to produce values, and returns a subscription handle representing this one run. The handle is what the caller keeps: it is how the screen later cancels and lets the source release what it holds. So a pipeline that is built and stored but never subscribed does nothing at all — no request, no error, no log line — and a pipeline that is subscribed while the handle is thrown away can never be stopped by its owner.

code

pseudocode · 11 lines
pseudocode
pipeline = messagesFrom(conversationId)
            .decrypt()
            .markAsRead()

// nothing has run yet: no connection, no decryption

subscription = pipeline.subscribe(
    onValue = function(message) { view.append(message) },
    onEnd   = function(reason)  { view.showEnded(reason) })

// the connection opens here, and `subscription` is the handle that stops it

go deeper

for a junior

Remember the one-line rule: nothing runs until something subscribes, and the subscribe call gives you a handle to keep. A screen with no data and no error usually never subscribed.

for a middle

Explain the mechanics: subscribing wires the chain, starts the source, and returns a per-run handle. Note that a fully in-memory source can finish before the subscribe call even returns.

for a senior

Show the operational consequence: silent screens come from never subscribing, and runs that outlive their owner come from discarding the handle. Make handle ownership explicit in review.

for a principal

Set the convention that every subscription has a named owner whose lifetime ends it, so that starting work and owning work are never separated across a codebase.

## A stream is a description until something subscribes A reactive source is a recipe for producing values, not the values themselves. Writing `messagesFor(conversation)` and chaining stages onto it builds an object that **knows how** to open a connection, decrypt each message and hand it on — but it has opened nothing and fetched nothing. The work begins at one moment: when a subscriber is attached to the end of the chain. That is why a screen that builds a pipeline and stores it in a field sits there silently: no request in the network log, no failure to explain it, nothing at all. Silence is the symptom of a missing subscription. Three things happen at that moment: 1. **The chain is wired.** Each stage attaches to the one above it, from the subscriber at the bottom up to the source at the top, so a path now exists in both directions — values will travel down it, and a cancel will travel up it. 2. **The source starts.** Whatever the source does to produce values — opening a connection, reading a file, arming a timer, registering with a live event feed — it does now, because a subscriber has asked for values. 3. **A handle comes back.** The subscribe call returns an object that stands for **this one run**: the caller's means of ending it early. ## What the handle is for The handle is the only part of the subscription the calling code holds directly, and it exists for one reason: a run that was started must be stoppable by whoever started it. - It **cancels**: asking the handle to cancel sends that request up the chain so the source can stop and release what it holds. - It **scopes ownership**: whoever holds the handle owns the run's lifetime, which is how a subscription gets tied to the screen that opened it. - It usually **reports whether the run is still live**, so cleanup code can avoid cancelling something that already ended. Discarding the handle is therefore not a stylistic sloppiness. It permanently removes the only lever the owner has, and the run continues until the source ends on its own — which, for a live conversation feed, is never. ## Built, subscribed, cancelled: what exists when | Moment | What exists | What is running | What the caller can do | |---|---|---|---| | Stages chained together | A description of the work | Nothing | Subscribe to it, or discard it harmlessly | | Subscribe called | A live subscription plus a handle | The source is producing | Receive values; cancel through the handle | | Cancel requested, or the source ends | A finished run | Nothing, once the source observes it | Subscribe again for a fresh run | The first row is what candidates miss. A described pipeline holds no connection, leaks nothing, and can be built in a constructor without consequence. It is inert. ## What subscribing does not promise Two honest refinements sit just past the basic answer, and interviewers like both. - **Subscribing does not promise that values arrive later.** A source backed by values already in memory may push every value and finish **before the subscribe call returns**. Code shaped as *subscribe, then store the handle, then decide what to do about early values* can be too late: the sequence is already over. Store state before subscribing, not after. - **Subscribing does not promise anything about where the work runs.** Whether the source's work happens on the caller's worker or elsewhere is a separate decision made by the pipeline, not by the act of subscribing. ## How to answer it in an interview Say the mechanism in one sentence — *nothing runs until something subscribes, and subscribing hands back the handle that stops it* — then give the two failure shapes it explains, because they are what the interviewer is really probing: - **Built but never subscribed:** a screen that shows no data and logs no error. The pipeline was assembled and nobody asked for values. - **Subscribed but the handle discarded:** a screen that works, and then keeps working after the user has closed it, because nothing can cancel it. Both shapes come from the same fact, stated from opposite ends: subscription is the boundary between describing work and owning a running piece of work.

  • The team stores the built pipeline in a field when the screen is constructed. Does that hold a connection open?
    No. A built pipeline is inert: it describes how to open the connection, transform values and finish, but holds none of those resources. Constructing and storing it is free, and discarding it needs no cleanup. Only a subscription owns running work, and only a subscription needs cancelling.
  • If the handle was discarded, is there any other way the run can end?
    Yes, but none of them is under the caller's control. The source may complete on its own, it may fail, or a stage inside the pipeline may cancel upstream as part of its own behaviour. For a live conversation feed none of those arrives, so a discarded handle means a run nothing can end.

Writing an order on a ticket costs the kitchen nothing; handing the ticket over is what starts the cooking, and the number you get back is how you call it off.

saying these in an interview costs you the question

  • Says the source starts producing as soon as the pipeline is built
  • Thinks a stored but unsubscribed pipeline holds an open connection
  • Treats the returned handle as the first value of the stream
  • Believes subscribing always returns before any value is delivered
  • Discards the handle and says nothing is lost by doing so