Slack Rebuilt Notifications for Millions of Users
Without a Single Breaking Change. Here's How.
Notification overload is one of the top three reasons users contact Slack support. Not security incidents. Not data loss. Ping anxiety.
That stat is embarrassing for a company whose product is literally communication. But what’s interesting isn’t the problem, it’s why it was so hard to fix.
The system wasn’t broken. It was incoherent.
Desktop and mobile had entirely separate preference systems that had grown apart over years. “Nothing” on mobile meant something different from “Off” on desktop. Not slightly different. Architecturally different. One disabled push notifications. The other disabled in-app badges too. Users changing settings on one device had no predictable effect on the other.
This is how trust erodes. Not with crashes. With settings that don’t do what you think they do.
The core design flaw was a tight coupling between what notifies you and how you get notified. If you wanted fewer interruptions on mobile, your only lever also killed in-app awareness. There was no way to say “show me everything in the sidebar but only push me for mentions.” You had to pick between overload or ignorance.
Four preference systems became one
The old prefs looked like this:
desktop: everything | mentions | nothing // Push on desktop
mobile: everything | mentions | nothing // Push on mobileThe word “nothing” is doing dishonest work there. Users who chose it thought they’d gone quiet. They hadn’t — they still got in-app badges. They just didn’t know it.
The new model decouples the two concerns cleanly:
desktop: everything | mentions // What activity to show
desktop_push_enabled: true | false // Whether to interrupt you
mobile: everything | mentions | nothingdesktop_push_enabled is new. Because it had no prior value in the database, the team could backfill every existing user based on whether they’d previously set “off”, no disruption, no migration emails, no support tickets. “Off” became “mentions with push disabled” at read time, which is exactly what it meant in practice anyway.
That’s a clean migration. Backwards compatible, rollback-safe, and behaviorally honest.


