skip to content

Two member collections of 50,000 ids each are intersected on every request — what changes when the store computes the intersection rather than the caller?

level: seniorimportance: should knowfreq 44%

answer

  1. neither collection crosses the network
  2. bytes scale with the answer, not the inputs
  3. the work moves, it does not vanish
  4. one question means two membership tests
  5. a stored result is a point-in-time answer

basics

~20 s

Neither collection crosses the network: one request returns the overlap alone instead of 100,000 ids over two round trips. The cost moves to the server, where the work occupies one operation other callers wait behind.

solid answer

~50 s

Computed in the caller, the intersection means two whole-collection reads, roughly 100,000 ids on the wire and a local pass over both — and the cost scales with the inputs, not with the answer. Computed where the collections already live, the request is one round trip and the reply is the overlap alone, so the bytes moved scale with the result. What you pay is server time: the work happens inside a single operation the server runs to completion, so a large intersection occupies the tier while other callers wait, which is why it is sized and not assumed. Two caveats matter. If you only need to know whether one id is in both, two membership tests beat any intersection. And server-side set algebra is not universal in this class: a store that only hands back the bytes it was given cannot do it at all.

go deeper

for a junior

Recall that a membership test and a set operation both run where the collection already is, so the collection itself does not travel — only the question goes in and the answer comes back.

for a middle

Compare the two paths on bytes and round trips, and note that the wire cost scales with the result server-side but with the inputs when the caller does the work.

for a senior

Add the price: the set operation is one unit of server work other callers wait behind, so the size is part of the design, and a stored result is a point-in-time answer that does not follow its inputs.

for a principal

Rule on which request paths may carry a computation whose cost scales with stored data at all, versus maintaining the answer incrementally on the write path.

## The two places the work can happen The question is where the intersection of two member collections is computed, and the answer changes what travels and who spends the time. **In the caller.** Two whole-collection reads, one per key. Roughly 100,000 identifiers cross the network and are materialised in the caller's memory, which then walks one collection testing each member against the other. The cost is proportional to the size of the inputs, every time, even when the overlap is three ids. **In the store.** One request naming both keys. The collections stay where they are; only the result comes back. The cost on the wire is proportional to the size of the answer. That is the whole idea, and it generalises past intersection to the other set operations: - the members common to both collections; - the members present in either of them; - the members of one that are absent from the other; - and, where the store offers it, the same computations written to a new key instead of returned. The unifying claim worth saying out loud in an interview is: **neither collection crosses the network**. ## What each path costs | | computed in the caller | computed in the store | |---|---|---| | round trips | two reads, then local work | one | | bytes on the wire | both collections in full | the result only | | memory spent | both collections in the caller's heap | none in the caller | | time scales with | the inputs | the inputs, but spent server-side | | effect on other callers | none | the work occupies the tier while it runs | | availability | works against any store | only where the server understands the collections | ## The cost you are buying with Moving the computation does not make it free; it makes it someone else's. The intersection runs as **one operation the server runs to completion**, so for its duration the tier is busy with it. Stores in this class reach that property differently — some by serialising execution, others by holding the entry while the operation runs — but the caller-visible consequence is the same: a big set operation is a big unit of work that other callers are behind. That is why the honest senior answer includes a magnitude. Fifty thousand members is routine. Two collections of ten million, intersected on every request, is a design that will show up as latency for everybody, and the fix is upstream — maintain the answer incrementally as members are added, rather than recomputing it per request. A second cost is the result itself. Where a store can write the outcome to a new key rather than returning it, that new entry is an ordinary entry: it occupies memory, it needs a lifetime of its own, and it is a **point-in-time answer** that is stale the moment either input changes. Treating a stored result as if it tracked its inputs is a real and common error. ## When not to do it at all 1. **You need one answer, not the whole overlap.** "Is this user in both groups" is two membership tests — two tiny replies, no set operation, no scan of anything. Reaching for an intersection to answer a yes-or-no question is the most common overreach here. 2. **The overlap is nearly the whole input.** If almost every member is in both, the result is as large as the inputs, and you have moved the bytes back onto the wire while also spending the server's time. 3. **The collections are not held by the same server.** Where the tier is split across nodes, whether one operation can see both keys at once is a placement question, and it belongs to the distribution subject — but it is a real precondition, not a detail. 4. **The store is byte-opaque.** A server that returns exactly the bytes it was given has no notion of members, so every set operation is necessarily the caller's work. This is not a deficiency to argue about; it is a fact to check before designing on the assumption. ## Keeping the tier's premise in view Both collections are ephemeral. Either can be evicted or lost on a restart, and the intersection of a full collection with an empty one is an empty result — which is not an error the store will report, just a smaller answer than expected. A design that acts irreversibly on an empty overlap has confused "no members in common" with "the collection is gone". The defensive habit is to check the inputs' size when the answer drives something consequential, or to treat an unexpectedly empty result as a signal to rebuild rather than as a fact.

  • The result is written to a new key instead of returned. What have you created?
    An ordinary entry, with all the obligations of one: it occupies memory, it needs a lifetime, and it holds the answer as it stood at that instant. It does not track its inputs, so any later change to either collection leaves it quietly wrong. Anything reading it must tolerate that staleness or trigger a recompute.
  • You only need to know whether one identifier is in both collections. What do you do?
    Two membership tests, one per key. Each sends an identifier and receives a yes or no, with no dependence on how large either collection is. Computing a full intersection to answer a single yes-or-no question spends the tier's time proportionally to the inputs to produce one bit.
  • The intersection is needed on every request and both collections are growing. What is the structural fix?
    Stop recomputing it. Maintain the answer as a third collection, updated when a member is added to or removed from either input, so the request path becomes a read instead of a computation. You trade write-path work and an extra entry for a request path whose cost no longer scales with the inputs.

Two clubs want to know which members they share. They can each photocopy the full membership roll and post both to a third party who compares them — everything travels, and the postage is the same whether they share two members or two thousand. Or they can ask the registry that already holds both rolls to report just the overlap: nothing travels but the answer. The registry clerk, however, is doing that comparison instead of serving anyone else at the counter, and the list they hand back describes the rolls as they stood at that moment.

saying these in an interview costs you the question

  • Pulls both collections into the caller and calls it equivalent
  • Thinks computing it server-side makes the work disappear
  • Assumes every in-memory store can compute set operations
  • Uses a full intersection to answer a single yes-or-no question
  • Treats a stored result as if it tracked its inputs
  • Reads an empty overlap as fact without checking the inputs exist