How Apple Push Notification service (APNs) works
How Apple Push Notification service (APNs) actually works: device tokens, the HTTP/2 handoff, and how a push reaches your iPhone, in plain English.

A user taps "Allow" on your notification prompt, and later that day your server decides they should hear about something: an order shipped, a backup failed, a match found. Between those two moments sits a piece of Apple infrastructure most developers use every day and never actually see: Apple Push Notification service, or APNs.
You don't strictly need to know how it works to send a push. But the day a notification doesn't arrive (or shows up six hours late, or stops reaching one specific user), the black box becomes your problem. Knowing the moving parts is the difference between "APNs is flaky" and "ah, that token got invalidated when they reinstalled."
The three players
Every push notification involves exactly three parties:
- Your provider server: your backend, the thing that decides a notification should go out.
- APNs: Apple's cloud service, the middleman that actually reaches the device.
- The device: the iPhone (or iPad, Mac, Apple Watch) running your app.
Your server never talks to the device directly. It can't. It talks to APNs, and APNs talks to the device. That indirection is the entire design: Apple sits in the middle so your server never needs to know where a phone is, whether it's awake, or which network it's on.
Step 1: the device gets a token
When your app first launches and the user grants notification permission, the operating system registers with APNs and gets back a device token (a long, opaque hex string that uniquely identifies this app on this device), a mailing address for one app on one phone.
Your app then hands that token to your server, which stores it. From that point on, "send a push to this user" really means "send to this token."
And here's the catch that causes half of all push bugs: the token isn't permanent. It can change when the user reinstalls the app, restores from a backup, or moves to a new phone. A token you saved last month might already be dead, and nothing tells you until you try to use it.
Step 2: your server talks to APNs
To send a notification, your server opens an HTTP/2 connection to APNs (api.push.apple.com on port 443), and makes a POST request to /3/device/<the-device-token>. Two things have to be right.
Authentication. You have to prove you're allowed to send. Modern setups use token-based auth: a JWT signed with a .p8 key from your Apple Developer account, using the ES256 algorithm, refreshed roughly every hour and sent in an authorization: bearer … header. The older approach is a TLS client certificate. Either way, it's credential plumbing you set up and then maintain forever.
The payload. A small JSON object built around an aps dictionary (the alert text, a badge number, a sound), plus headers like apns-topic (your app's bundle ID) and apns-push-type. The whole thing has to fit in 4 KB (4,096 bytes). That's not much. A push is a nudge, not a data channel.
Step 3: APNs delivers it
This is where the design pays off. Every Apple device keeps a single persistent connection open to APNs the entire time it's online: one connection, shared by every app on the phone. Your app doesn't hold its own socket open draining the battery; the OS maintains one pipe for everybody.
When APNs receives your request, it looks up the device behind that token and pushes the payload down that existing connection. The OS wakes your app or simply shows the alert. On a good day the whole trip takes well under a second.
If the device is offline, APNs holds the notification and delivers it when the phone comes back, but it only keeps the most recent one per app. Send five alerts to a phone that's been off all day and it may see just the last. APNs is best-effort, not guaranteed delivery, and Apple is upfront about that. The how it works page walks through the same flow from the sending side.
What happens when a token goes stale
Remember the token that can change out from under you? When you send to a dead one, APNs tells you. A 410 response with Unregistered means "stop sending to this token. It's gone." A 400 with BadDeviceToken means it was never valid for this environment (sandbox tokens don't work in production, and vice versa).
You're expected to act on these: delete the dead token from your database so you're not hammering APNs with sends that will never land. Ignore the errors and your delivery rate quietly rots while everything looks fine.
The part nobody puts in the tutorial
None of the individual pieces here are hard. The tax is that there are so many of them, and they never stop needing attention: generating and rotating the JWT, keeping the HTTP/2 connection healthy, pruning stale tokens, juggling sandbox versus production, staying under 4 KB, decoding APNs error codes. For a full consumer app with millions of users, that's justified. It's the cost of doing the job right. For "ping my phone when the nightly backup fails," it's absurd: a weekend of building push infrastructure to send yourself three notifications a day.
The shortcut, if you just want your phone to buzz
That gap is exactly what TheNotificationApp fills. It keeps the APNs connection, the auth keys, and the token bookkeeping on its side. You send one HTTP POST:
curl -X POST https://thenotification.app/api/sendNotification \
-H "app_key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Backup finished",
"body": "Nightly backup completed in 4m 12s",
"link": "https://status.example.com"
}'
That's the entire integration. One endpoint, one header, one JSON body, and every step of the three-part dance above happens behind it. Under the hood it's the exact same APNs pipeline; you just don't own the plumbing. The API reference has the full field list, and if you want the higher-level view first, what a push notification API actually is covers the concept without the protocol detail.
A notification body can carry error messages or customer names, too: TheNotificationApp stores none of it and hosts in Switzerland, which is a real difference if that data matters to you (why that matters for push).
The tradeoff, with the real number
Fair warning: the free tier is 100 notifications total: a lifetime allowance, not a monthly reset. That's plenty to wire up a few genuine "something's wrong" alerts and run on them for months. But point it at a chatty webhook that fires on every request and you'll burn through 100 in an afternoon. Put noisy events behind a threshold, or move up to Pro at $2.99/month for 1,000 a month.
So, in one line
APNs is a token, a middleman, and a persistent connection quietly handling the last mile to every iPhone on Earth. Worth understanding if you're building a full app, and worth skipping entirely if you just want your scripts to reach your pocket. If it's the latter, TheNotificationApp is worth a look; the free tier is enough to prove it to yourself this afternoon.
What sits on top of APNs
Where the plumbing meets the things you actually care about:
