Four Screens Showed Four Different Numbers For the Same Thing
Bakery Buddy puts a small green number on a few different screens. It's meant to answer one question: is there something here Buddy thinks you should look at? A new inquiry. A drafted email waiting on your approval. An order that's unpaid.
For a while, that number gave four different answers to the exact same question, on the exact same account, at the exact same moment.
Four numbers, one question
Orders showed 20. Automations showed 21. Reports showed 17. The toolbar above the orders table said "14 to review." All four were supposed to mean roughly the same thing: work waiting on the baker. None of them agreed, and there was no way to look at the screen and know which number, if any, was telling the truth.
The reason wasn't a math error. It was that four different places in the code were each answering "what needs attention?" on their own. One counted new inquiries. Another counted drafts, but only the ones on the page it happened to be looking at. A third recomputed the same idea from scratch, in its own query, with its own slightly different rule for what counts. Every one of those implementations compiled fine and passed its own tests. Nothing about writing four separate answers to one question looks wrong from inside any single screen. It only looks wrong once you stand back and read all four numbers at the same time, which is exactly the thing a baker does without thinking about it and a build check never does at all.
One list instead of four
The fix wasn't a smarter formula. It was refusing to let there be four formulas. Every badge in the app now reads from one single list of things that need a baker's attention, built by one piece of code, computed once. Nothing stores a count anywhere. No screen runs its own version of the question. A badge is just a filtered view of that one list, however many screens it shows up on.
The three real reasons something lands on that list stayed exactly what they always were, an order came in, a draft is waiting, an order is unpaid. What changed is that there's now exactly one place that decides that, instead of three or four places quietly drifting apart from each other.
What one list buys you that four never could
- A number on a single order can now mean something specific. One order can carry two reasons at once (it's a new inquiry and it has a balance due), so its badge reads 2. No per-screen count could ever have said that, because none of them were looking at individual records in the first place.
- Clicking a badge now goes somewhere useful. Tap the number and it opens the assistant panel already showing exactly what it counted, on the record it's attached to. Before this, a badge on a screen that couldn't show that detail was a dead end. Now every badge lands.
- Badges clear the moment the work is done, not on the next reload. Approve a draft and the count drops right there. That only works because the badge and the action both point at the same underlying list. Two separate implementations can't clear each other in real time; they can only disagree until someone refreshes.
We also deleted a second, unrelated way the app used to flag a row that needed attention. It hadn't been used anywhere in months. Keeping a second concept alive next to the new one would have just been a second place for the same drift to start over.
Verifying it meant more than a green build
A build passing here would have proven almost nothing. Four separate, individually-correct-looking implementations is exactly the bug, and a typecheck can't see across files to notice that two of them answer the same question differently. The only real check is comparing the badge to the actual data behind it: does the number on screen equal the length of the list it's supposed to be counting, for a real account.
For Bakery Buddy's own test account, that came out to a single combined total of open work items, checked against the database directly rather than trusted by eye. For Marin's real studio, the same list is bounded by her actual open work rather than the size of her order history, so the badge stays a real, checkable number instead of a query that gets slower and vaguer as her order count grows into the hundreds.
The part that isn't really about badges
None of this is specific to green numbers in a bakery app. It's the same failure mode as any dashboard, any notification count, any "X items need your attention" indicator that shows up in more than one place in a product. The moment two screens each compute their own version of "how many," they will eventually disagree, quietly, and nothing in a build or a type system will catch it, because each one is individually correct. The only fix is the boring one: pick one place that owns the answer, and make every screen that displays it read from there instead of re-deriving it.
If your own product shows the same count in two different spots, go check right now whether it's actually the same query twice, or two queries that happen to agree today.
Frequently Asked Questions
What was actually wrong?
Four different screens in Bakery Buddy each showed their own count of 'work needing a baker's attention,' computed by four separate pieces of code. On the same account, at the same moment, they read 20, 21, 17, and 14. None of them were reading the same underlying list, so there was no way to tell which number was correct.
Why didn't a passing build catch this?
Each of the four implementations was individually correct and compiled fine on its own. The bug only exists when you compare all four numbers to each other, which a typecheck or a build never does. It only shows up when a person looks at two screens at once and notices they disagree.
What's the actual fix?
Every badge in the app now derives from one single list, computed in one place, instead of each screen running its own query with its own rule for what counts. A badge is a filtered view of that one list, so every screen that shows a count is, by construction, looking at the same answer.
Does this only matter for notification badges?
No. Any product that shows the same count, total, or status in more than one place has the same risk. Two independently-computed answers to one question will eventually drift apart, silently, and the only real fix is picking one source of truth and having everything else read from it.
I build Bakery Buddy for my wife Lindsay's cake studio, Marin Cake Studio, and I check every number the app shows against her own account before I trust it.
Ready to put this into practice?
Join the Waitlist