The Notification Bell Got Blamed. It Wasn't the Bell.
Bakery Buddy used to have a notifications bell in the header. It got retired because it was polling the server every 60 seconds on every screen, all day, for one user. Two days after that shipped, Lindsay reported the bell was back, and it was more annoying than before, popping up on the Orders page over and over while she worked.
The bell really was gone. What she was looking at was a completely different popup, and the fact that it looked exactly like a repeating notification was the whole bug.
A toast with one job
Weeks earlier, a small feature shipped alongside the bell: whenever a customer submitted a cake request through the bakery's public website, a toast slid in. "New cake request ๐," the customer's name, the event date, a Review button, a Dismiss button. It was supposed to fire once, the first time you saw a given new request, and then leave you alone.
To make "once" work, it saved the request's id to `sessionStorage` the moment it fired, under one fixed key. The next time the component mounted, it would check that key, see it already matched, and stay quiet.
That works fine for exactly one open request at a time. Marin's account had 23.
Clearing the queue is what re-armed it
The toast only ever remembered the single most recent request it had shown. So the first time Lindsay opened a new website inquiry and worked it, the toast's saved id no longer matched anything current, because there were 22 other open requests still sitting there, and the next-newest one became the new "latest." The moment she navigated anywhere in the app, the component mounted again, checked its one saved id, didn't recognize the new "latest," and fired again. Different customer, different date, same ๐.
The Dismiss button didn't help, because there was nothing left for it to persist. The write to `sessionStorage` already happened the instant the toast appeared, before she had clicked anything. Dismiss just closed the visible card. It was never the thing standing between her and the next popup; that was the request queue itself, and working through it was the trigger.
There was also no way to turn it off. No setting, no preference, no route it stayed off of. It was mounted once, unconditionally, for every authenticated page in the app, which is also why it kept showing up no matter where she navigated to get away from it.
Why it read as the bell
The bell had been announced as gone two days before this was reported. Lindsay had no reason to think a brand-new, unrelated popup had shipped in between, and every surface symptom matched what the bell used to do: an interruption while she was mid-task, that kept coming back no matter what she clicked. She correctly diagnosed "a notification that won't stop repeating." She just had the wrong notification.
The fix
The toast got deleted outright, not patched. Its whole reason for existing was to alert Lindsay to a new request, and the Orders navigation badge already counted new website requests on its own, correctly, every time, with no "have I seen this one" logic to get wrong in the first place. There was nothing to save by keeping a second, worse way of saying the same thing.
What generalizes past one popup
A "have you seen this" memory that stores one item instead of one record per item isn't really tracking what's been seen. It's tracking what was most recently new, which silently resets itself the instant the world has more than one thing going on at once. That's a fine design for something that can only ever have one open item. It's a trap for anything with a queue behind it, because working the queue is exactly the action that makes the next item look unseen again.
And a Dismiss button only means something if the state it's dismissing is still there to act on. If the "you've seen this" write already happened at mount, before the user did anything, dismiss is cosmetic. It closes the card. It doesn't close the loop.
The other lesson is really about diagnosis, not code. Chad's own first move on hearing "the bell is back" would have been to check the bell's own code, since that's the thing being reported. It wasn't the bell. If a symptom matches something you already fixed, it's worth confirming the two are actually the same component before assuming the old fix regressed, especially in a codebase with more than one thing capable of producing the same kind of interruption.
If anything in your own product has a "seen it" flag, check what it's actually keyed on. A flag that can only remember one thing at a time isn't a seen-state. It's a coin flip that happens to land right as long as nobody's queue ever has more than one item in it.
Frequently Asked Questions
What was actually wrong with the popup?
A toast that announced new website-submitted cake requests stored its 'already seen' memory as a single sessionStorage key holding one request id. With 23 open requests on the account, clearing any one of them changed which request counted as 'latest', so the saved id stopped matching and the toast fired again on the next page load, for a different request each time.
Was this actually the notifications bell coming back?
No. The bell had been retired two days earlier for an unrelated reason (it was polling the server every 60 seconds on every screen). This was a separate, smaller toast for website-submitted cake requests. It just produced the same kind of symptom, a repeating interruption, so it read as the bell regressing.
Why didn't the Dismiss button fix it?
Dismiss only closed the visible card. The 'seen' write to sessionStorage happened the moment the toast appeared, before the user clicked anything, so there was nothing left for Dismiss to actually persist.
What was the fix?
The toast was deleted, not patched. The Orders navigation badge already counted new website requests correctly on its own, with no seen-state to get wrong, so there was nothing worth saving by keeping a second, buggier way of surfacing the same information.
I build Bakery Buddy for my wife Lindsay's cake studio, Marin Cake Studio, and this is the bug that taught me a popup without an off switch is never a small thing to ship.
Ready to put this into practice?
Join the Waitlist