ଅ essay

product · engineering · savesync · design-process

A Wrong Suggestion Costs More Than a Missing One

Notes from SaveSync on silent failure, honest error messages, and why suggestion features should be judged on precision, not coverage.

A missing suggestion costs a few seconds of typing. A wrong one costs a junk tag in a place the user owns, forever.

In August, SaveSync’s mobile app got a feature request: AI tag suggestions. When you save a link, offer some tags. The first version took the longest words in the page title that weren’t stop-words.

I ran it against real titles. It suggested introducing, guide, 2026, announcing and everything.

Coverage is what makes a demo look good. It isn’t what makes a feature good.

The asymmetry

A missing suggestion costs a few seconds of typing. A wrong suggestion is one tap away from becoming a junk tag, inside a vocabulary the user owns, and there was no screen anywhere in the app to clean tags up. So the cost of a bad suggestion isn’t the moment. It’s forever.

Suggestion lists should be judged on precision, not coverage. Offer less, and be right.

What we shipped suggests only two kinds of tag:

  1. Tags you already own, when they appear in the title or the address, matched on whole words. It can’t invent anything, because every label it can offer is one you chose. This is also where the real value was: it’s how the fifteenth design link gets your existing design tag instead of a fourteenth near-duplicate.
  2. A short list of sites whose subject isn’t in dispute. arxiv is a paper. Figma is design. That covers the person who has no tags yet.

We dropped the word “AI” from it, too. A stop-word list behind a sparkle icon is a promise the code can’t keep. There was already an open issue proposing the real version, built on the embeddings search computes anyway. Shipping the cheap version under the expensive name would have quietly closed that issue without solving it.

Silent failure is the expensive kind

The tag feature was one ticket in a batch of four that arrived the same week. None of them crashed. That was the problem.

A save quietly landed in two collections instead of three. A menu quietly rendered in the wrong typeface. A share quietly took four seconds and your place in the app you shared from. Nobody files a bug report about any of that. They form an opinion that the app is unreliable, and then they stop reaching for it. That opinion is never in an error log.

Loud failures get reported and fixed. Silent ones get blamed on the product.

Say what state the data is in

The error message for a failed save used to read Could not save: API Error: 4. It was built from the HTTP status and then cut off at 30 characters, so the one part that explained anything was the part that got cut.

Now it says Not saved, then why: no connection, you’ve hit your save limit, SaveSync is having trouble. The word changed too. “Failed” describes what the software did. “Not saved” describes your data, which is the thing you actually care about.

An error message has one job: tell the person what to do next. “You’ve hit your save limit” says upgrade. “No connection” says wait. Same failure, completely different relationship with the product.

Things I’d carry to the next product

  • When several bugs share a shape, the shape is the bug.
  • A comment that justifies code is where bugs hide. “For backwards compatibility” was the reason nobody questioned the write that was deleting people’s collections.
  • A fast path is only safe if its failure mode is the slow path.
  • Say what state the data is in, not what the software did.
  • A wrong suggestion costs more than a missing one.

The long version, with the trigger that ate collections and the 13.7-second page, is in the SaveSync case study.

The World Beneath

turn-based roguelike · 8×8 textmode · CRT

Under the site there’s a small world. Click the screen to start: pick a companion, find the ten caches, and see how far down the temple goes.

The ring

water douses fire · fire burns root · root grounds spark · spark shocks water. Lead with what beats what’s in front of you: ×2 one way, ×½ the other.

Walk
arrows, WASD, or click
Act
Enter · Z waits · M menu
Margins
more marks hide in long reads
·