skip to content

A service creates a new key in an in-memory store on every request and deletes none. What does the store do about that growth?

level: juniorimportance: should knowfreq 55%

answer

  1. nothing in the write path objects
  2. no schema, so no count to check
  3. the design shows only in the total
  4. memory is the first real pushback
  5. bound the factor, or attach a lifetime

basics

~20 s

Nothing. Each write is individually valid and there is no schema against which a key count could be judged, so a key-minting design shows up only in the total entry count and the memory used, never in a refused write.

solid answer

~50 s

The store has no opinion about it. A write is one key and one value, and there is no table definition, no declared shape and no expected row count to compare it against — the write that creates the ten-millionth key is indistinguishable from the one that created the first. The **distinct-key count**, meaning the number of separate keys a scheme creates in production, is a property of the design, so nothing in the write path can check it. What eventually pushes back is memory: the total climbs until the tier reaches its ceiling, and what happens there varies by store and by configuration. The fix is in the design — find the segment of the key template that grows with traffic or time, bound it, or attach a lifetime to the entry so the store removes it later.

go deeper

for a junior

Recall that a write is just a key and a value, with no shape to violate. Nothing rejects a design for producing too many keys, so the growth appears only in the total entry count and the memory used.

for a middle

Explain the mechanics: the distinct-key count is the product of the factors in the key template, it is a property of the design rather than of any write, and memory is the only thing that eventually pushes back.

for a senior

Show the production habit: the total entry count on a chart beside memory, the unbounded factor named before launch, and a stated position on what your tier actually does when it reaches its ceiling.

for a principal

Frame it as ownership. On a shared tier, someone must own the question of which team's design is allowed to grow without limit, because the store will not raise it and the first party to notice is whoever is on call.

An in-memory store of this class accepts a write as one key and one value, and has nothing to compare that write against. There is no table definition, no declared column, no expected row count, no planner estimating how many distinct values a column will hold. The write that creates the ten-millionth key looks exactly like the write that created the first, and the store answers both the same way. ## The count is a property of the design, not of any write The **distinct-key count** is the number of separate keys a scheme will create in production. It falls straight out of the key template. One key per user is bounded by the number of users. One key per user per day is unbounded in its second factor: nothing stops the days accumulating. One key per request is unbounded in a factor that grows with traffic and never comes back down. That number belongs to the *design*. No single write carries it, so no single write can be measured against it. This is the structural difference from a schema-bearing engine, where the shape of the data was declared once and a write that does not fit that shape is refused. Here there is no shape, so there is nothing for a write to fail. ## Where the design does eventually become visible | Where it shows | What you see | How late it is | |---|---|---| | the write path | nothing at all | it never shows here | | the total entry count | a line that climbs and never comes back down | early, if someone put it on a chart | | memory used | the same climb, priced in bytes | later, and it is the binding one | | the memory ceiling | whatever your tier is configured to do there | far too late to redesign | Only two things genuinely push back, and both are indirect: - **Memory.** Every key is bytes, every value is bytes, and every entry carries fixed bookkeeping on top of both. The total is what the ceiling applies to. - **Whoever is watching.** A chart of the total entry count is the earliest honest signal, because it moves before memory does on designs with small values. The store itself does none of the things people expect. It does not rate-limit key creation. It does not warn. It has no notion of "too many", because it has no notion of how many there should be. ## What varies between stores, and what does not - **Whether a container above the key exists.** Where the store offers a named container above the key, it isolates names and nothing more: the containers share one memory budget, one process and one operator, so no container bounds anyone's key count. - **One node or several.** Where the keyspace is split across nodes, the figure that matters is the total across all of them. Per-node counts can each look comfortable while the total is enormous, and an uneven template can fill one node first; how keys are assigned to nodes is a separate subject. - **The ceilings.** How long a key may be, and how large one entry may be, differ between stores by an order of magnitude or more. There is no general number — find your store's and treat it as a premise of your design rather than as a fact about stores. - **What happens at the ceiling.** Some deployments refuse further writes, some remove existing entries to make room, some are killed by the operating system. That behaviour is its own subject; the point here is that you do not want the arithmetic to be settled there. What is universal is the part that matters for this question: no store in this class rejects a write on the grounds that the design behind it will eventually produce a hundred million keys. ## What a working answer sounds like 1. **Name the unbounded factor.** Read the key template as a product of factors and say which one grows without limit — a request identifier, a timestamp at fine granularity, a query string, an event sequence number. 2. **Bound it, or give the entry a lifetime.** Either the design changes so the factor disappears — one entry per user rather than one per request, overwritten in place — or each entry carries a deadline after which the store removes it. How those deadlines behave is a separate subject; here it is simply the other lever. 3. **Put the total on a chart** next to memory used, and treat a line that only ever rises as a design defect rather than as capacity news. 4. **Redo the arithmetic when the business grows.** The scheme that was fine at fifty thousand users is the same scheme at five million; only the multiplier moved.

  • The keyspace is split across several nodes. Does that change what you watch?
    Not the arithmetic, only where you read it. The figure that matters is still the total across all nodes, which means summing per-node counts rather than trusting any one of them. An uneven template concentrates its busiest branch on one node, so that node reaches its ceiling while the others look idle. How keys get assigned to nodes is a separate subject; the watching is the same.
  • Where do key-minting designs usually come from in practice?
    From a key template that embeds something unbounded, usually without anyone deciding to. A request identifier, a timestamp at second granularity, a full query string, a rendered parameter list — each turns one logical thing into a new key every time it is seen. The test is to read the template as a product of factors and ask which factor has no upper bound.

saying these in an interview costs you the question

  • Thinks the store refuses writes once there are too many keys
  • Assumes the store removes old entries on its own, with nothing attached to them
  • Says memory is fine today, so the key design is fine
  • Treats a key with a tiny value as costing nothing
  • Expects a warning or a slowdown to announce the growth in time