All posts
Notifications

Push Notifications Are From Hell

3 min readKnoli Team

That might sound dramatic, and really, I am being a bit dramatic, but if you've ever tried to implement them properly, especially on iOS, you already know there is a lot to unpack. On paper, it feels simple: send a message, the user taps it, the app opens. In reality, it's a tangled system of moving parts where anything can (and will) break.

I've been deep in this recently, and integrating push notifications into my polling app has been one of the more frustrating technical challenges so far.

High-Level Overview

At a high level, push notifications seem straightforward:

  • Get a device token
  • Send it to your backend
  • Trigger a notification when something happens

But each of those steps hides its own set of problems.

iOS Complexity

On iOS alone, you're dealing with:

  • APNs (Apple Push Notification service)
  • Device token registration and refresh cycles
  • Permission handling (which users can deny, delay, or revoke)
  • Background app states and delivery rules

Then layer in Firebase Cloud Messaging (FCM), which is supposed to simplify things, but actually introduces another abstraction layer that you now have to debug when things go wrong.

So now instead of one system, you're juggling:

  • Apple (APNs)
  • Firebase (FCM)
  • Your backend
  • Your frontend app

Throw in another 'ball' there if you have a separate backend that runs scheduled jobs. If a notification doesn't arrive, you're left asking: which part failed?

The Critical User Experience Gap

In a social polling app where timing matters (e.g., "new poll", "your poll is trending", "results are in"), notifications become critical. If your token handling and error handling aren't tight, users simply don't get notified, and you don't always know they missed something. They can't even tell you they missed a notification if they don't know they are supposed to get one.

You also have to map:

  • One user → multiple devices
  • One device → one active token (maybe)

That relationship alone adds backend complexity that most people underestimate.

Testing Challenges

Now you could probably see why, if push notifications are hell, testing is the heat of the hellfire (hardest part of this entire process), the part that makes you want to give up.

Unlike most features:

  • You can't reliably simulate real-world delivery
  • Timing is inconsistent
  • Notifications can be delayed, dropped, or silently fail
  • Debugging is limited and often unclear

You end up in this loop:

"Did it send?"

"Did it arrive?"

"Was the app in the right state?"

"Was the payload correct?"

And sometimes… it just doesn't work, with no clear reason why.

This is where having a group of testers has been invaluable. Getting real feedback from actual devices, different usage patterns, and different network conditions has been the only way to build confidence that things are working.

The Deep Linking Problem

One of the biggest design challenges I ran into is what happens after the user taps the notification.

Initially, I passed data to the frontend so that tapping a notification would simply open the app. That worked—but it wasn't enough.

In a social app context is everything.

If a notification says:

  • "New poll you might like"
  • "Your poll is gaining traction"
  • "Someone voted on your poll"

The user expects to land directly on that exact poll. So I had to build a single poll view, another common social network design pattern that I thought I just didn't need, but where a user's feed is (personalized, time-based, and constantly shifting), it was impossible for me to 'find' the poll the notification was related to.

Systemic Impact

Push notifications seem like a growth feature, and they are, but they force you to tighten up your entire system:

  • Data modeling
  • Navigation
  • Backend structure
  • UX expectations

They expose every weak assumption you've made.

Ping! I just got a notification, 'so I gotta run'.

'But yeah!'… push notifications are from hell.

But they're also one of those features that, once they finally work properly, make you and your app feel alive.