The previous piece ended at the search box, which is where most products send people once the list stops working. So it’s worth asking what that box actually does, because the common implementation — match this string against one column, exactly — answers a question almost nobody asks. People don’t search with the value stored in the database. They search with what they remember.

What they remember is partial and slightly wrong. The vendor’s name minus the “Inc.” Somebody’s first name and the first letter of their last. The invoice as “the one for about four thousand.” A reference number typed with dashes when it’s stored without them, or without when it’s stored with. Every one of those returns nothing from an exact match, and “no results” is a uniquely bad answer because it’s indistinguishable from “this doesn’t exist.” The person doesn’t conclude the search is limited; they conclude the record is gone, and then they either recreate it or ask someone.

Most of the distance here is covered by unglamorous normalization rather than anything clever. Case folding, trimming, stripping punctuation from identifiers on both sides of the comparison, matching on prefixes rather than whole strings, searching across the two or three fields people actually use to identify a thing rather than only the canonical name. None of that is machine learning; it’s just refusing to require that the person type it exactly as it was stored. The gap between “exact match on name” and “reasonable match on a few normalized fields” is where nearly all the perceived quality lives.

Then there’s ranking, which matters as soon as results stop being empty. A search that returns four hundred things is a different failure with the same cause — the person still can’t find what they want, and now they have to read. Useful ordering usually isn’t textual relevance; it’s some blend of how well it matched and how likely this person is to want it: things they’ve touched, things in their part of the organization, things still active rather than closed three years ago. Sorting purely by string similarity is defensible mathematically and often useless in practice, because the query’s meaning depends on who’s asking.

The archived-record question is worth deciding explicitly rather than inheriting from whatever the query happened to do. If deleted or completed items are excluded, someone searching for last year’s record gets “no results” and learns the wrong thing. If they’re included silently, live and dead records blur together. The version that works is including them and saying so — marked, grouped, or behind a toggle that’s visible before it’s needed. Either behavior is fine; the failure is when the user can’t tell which one they got.

And when there genuinely is nothing, the empty state is doing more work than any other screen in the feature. It’s the moment a person decides whether the product is broken or their query was. Saying what was searched, offering the obvious relaxation — fewer words, spelling variants, include archived — and giving a path to create the thing turns a dead end into a next step. That’s a small amount of copy and layout guarding the outcome the whole feature exists to prevent.