Your in-memory store offers no incremental traversal at all, yet you need an inventory of what it holds; how do you get one?
answer
- traversal is not universal
- a key you cannot name is unreachable
- reconstruct the set from outside
- template plus identifiers you can iterate
- derivable keys beat any walk
basics
~20 sNot from the store: reconstruct the key set from outside - the system of record, the key template applied to identifiers you can iterate, or a list the write path records. A store without traversal answers only for keys you can already name.
solid answer
~50 sSome stores in this class deliberately expose no way to walk the keyspace: the only address is a key you already hold. The inventory therefore has to be reconstructed from outside the store. In order of preference: derive the key set from the **system of record** by applying the key template to identifiers you can already iterate, and address the store by key; or have the **write path** record what it wrote, which is an application-maintained index and a permanent commitment to keeping it true; or, for a one-off, take a copy that is not serving traffic and inspect it there with operator tooling rather than on the live node. What you cannot do is discover keys you have no other trace of — on such a store those entries are unreachable by design, which is an argument for a naming convention that makes every key derivable in the first place.
go deeper
Recall that some stores in this class only answer for a key you already know, so the list of keys has to come from somewhere other than the store.
Explain how to reconstruct the set: the key template applied to identifiers from the system of record, and why that is exact where a walk is not.
Show the judgment call: which of the four sources fits the requirement, what an application-maintained index commits you to, and when an entry lifetime removes the need entirely.
Set the rule: keys should be derivable from data you already own, so no design depends on an operation that half this product class refuses to offer.
Traversal is not a property of the class. Some in-memory stores expose an incremental walk, some expose only an all-at-once listing, and some expose no enumeration of the keyspace whatsoever. On the third kind, the only way to reach an entry is to already know its key — and a design that assumed otherwise discovers this during a migration, which is the worst possible moment. ## What `no traversal` actually means It is not that enumeration is discouraged or slow. There is no operation that returns keys you did not supply. A key you cannot name is, from the application's point of view, gone: it still occupies memory, it still counts against the memory ceiling, and it will still be removed eventually by its entry lifetime or under pressure, but nothing you can call will ever hand it back to you. ## Why a store would choose that It is a deliberate trade, not an omission. - **Every operation stays cheap and predictable.** No operation exists whose cost tracks the distinct-key count, so no caller can accidentally issue one and no operator has to defend against it. - **The data structures stay free.** Supporting a stable walk constrains how the store may reorganise its internal table while serving. - **Distribution stays simple.** Where the keyspace is split across nodes, an enumeration that means anything globally needs coordination the store would rather not own. - **The operator has one less footgun.** On a shared tier the dangerous operation is the one a single careless caller can issue against everybody else, and this store simply does not have it. A candidate who calls the absence a missing feature has missed the argument. The store is refusing to offer an operation that is dangerous on the stores which do offer it. ## Where the inventory actually comes from 1. **The system of record.** If the key template is `tenant, entity, identifier`, then every key you care about is a pure function of rows you can already iterate. Generate the keys, address the store by key, and you get an exact, resumable, parallelisable inventory whose cost tracks the rows rather than the keyspace. This is the answer in most designs, and it is stronger than any walk, because it is also complete. 2. **The write path.** Have whoever creates an entry also record its key — an application-maintained index, which the store did not build and will not repair. It answers `what is in there` directly, and it commits the team to keeping it true forever, including after crashes, partial writes and entries that expired without anyone telling the index. 3. **A copy that is not serving.** For a one-off audit, inspect a copy of the dataset away from the live node, using whatever operator tooling the deployment offers. It is a moment in the past, and it is fine for a question nobody will answer destructively. 4. **Bounding the problem instead.** Often the real requirement is not an inventory but a guarantee — that nothing lingers. An entry lifetime on every entry provides that without anyone ever listing anything. ## The trick that looks clever and is not Generating every key the template could possibly produce and probing each one works only when the identifier space is small and enumerable. Over user identifiers it is an exact, cheap inventory; over anything with a random or hashed segment it is unbounded, and probing your way through it puts more load on the tier than the listing you were avoiding. Use it when the identifiers come from somewhere you can iterate, and recognise it as the same move as deriving from the system of record. ## What this says about designs that depend on walking | design | on a store with a walk | on a store without one | |---|---|---| | find entries by key | fine | fine | | find entries by a value inside them | needs an application-maintained index | needs an application-maintained index | | sweep for orphaned entries | a best-effort walk | impossible from inside the store | | count entries under a prefix | approximate at best | derive it, or count on the write path | The row that matters is the third one. If a system's only plan for cleaning up after itself is to walk the keyspace and look, that plan does not survive a change of store, and it was never exact even on a store that allows it. The durable fix is to make every key derivable from data you already own, and to put an entry lifetime on anything that would otherwise need finding later.
- Why would a store deliberately offer no way to enumerate its keyspace?To keep every operation's cost independent of how much is stored. Enumeration is the one operation whose price tracks the distinct-key count, and on a shared tier a single careless caller issuing it hurts everyone. Refusing to offer it also leaves the store free to reorganise its internal structures while serving, and avoids the coordination an enumeration would need once the keyspace is split across nodes.
- What does deriving keys from the system of record give you that a walk never can?Completeness and exactness. The set comes from data that is transactional and iterable, so there are no repeats, no coin-flip arrivals and no instant to argue about, and the cost tracks the rows you care about instead of the whole keyspace. It is also resumable and parallelisable. It answers only what should exist, which is why orphan-hunting still needs a different mechanism.
saying these in an interview costs you the question
- Assumes every store in this class can enumerate its keyspace.
- Calls the absence of traversal a missing feature rather than a trade.
- Probes a random or hashed identifier space key by key.
- Plans to clean up orphaned entries by walking and looking.
- Builds an application-maintained index without owning its repair.
- Runs an all-at-once listing on the node taking live traffic.