Concepts / Real-time and media / Push notifications

Push notifications

Reaching a device that is asleep, through APNs and FCM.

01The intuition

The problem it solves

Asha's phone is in her pocket, screen off, the chat app closed. Ravi sends her a message. The app is not running, so it holds no open connection; the server has nothing to write to. If every app kept its own connection open all day, a phone with 50 apps would hold 50 sockets, each waking the radio for its own heartbeat, and the battery would be flat by lunch.

The operating system solves this once for everyone. Apple's APNs and Google's FCM keep a single connection from the phone to one of their servers. Your server does not talk to the phone at all; it hands a small message to APNs or FCM with a token that identifies the device, and the platform delivers it, wakes the app if needed, and shows the banner.

Build it one piece at a time

Step 1: register a token. When the app first runs it asks the operating system for a device token, a long opaque string, and sends it to your server. Store it against the user: one user may have several devices.

UserDevicePlatformToken (shortened)Last seen
AshaphoneAPNsa91f…today
AshatabletFCM7c02…3 months ago

Step 2: send through a queue, not from the request. When Ravi's message arrives, the chat service should not call APNs inline; that adds a slow network call to his send. It drops a job on a queue: "notify Asha, message 4471". A fleet of notification workers reads the queue, looks up Asha's tokens, and calls the platform APIs.

Step 3: decide whether to send at all. Before calling the platform the worker checks: is Asha currently online with an open socket (then the socket already delivered it), has she muted this chat, is it 3 a.m. in her time zone for a non-urgent notice, and has this message already been sent (a dedup key such as user id plus message id). Most pushes are suppressed here, which is the point.

Step 4: handle the platform's answers. APNs and FCM reply per token: delivered, invalid token, or rate limited. An invalid token means the app was uninstalled; delete it so you stop paying for it. Rate limited means back off with a delay and retry. The worker must not retry a delivered push, so each attempt carries the same dedup key.

Step 5: collapse and prioritise. Twenty messages in one group chat while Asha is asleep should become one banner, "20 new messages", not twenty. Give each push a collapse key, and let the platform replace the earlier one. Give urgent pushes (a ride has arrived) high priority so the phone wakes immediately, and the rest low priority so the platform batches them and saves battery.

Why it works, with the numbers

The guarantee is weak on purpose: a push is best effort, delivered by a third party, sometimes delayed by the phone's power state, and never the only copy of the data. The message itself lives in Asha's inbox on your servers; the push is a doorbell. For capacity, if 200 million users receive 20 pushes a day:

200,000,000 × 20 ÷ 86,400 s ≈ 46,000 pushes per second on average, perhaps 5× that at the evening peak

Each push is one HTTP/2 request to APNs or FCM of a few hundred bytes, so a few dozen workers keep up, and the queue absorbs the peak. The failure modes to name: tokens go stale (handle the invalid-token reply), the platform throttles bursts to one app (spread sends over seconds), and a push can arrive before the data is readable if the write was not yet replicated, so the app should fetch on open rather than trust the payload.

The trade-off you must say out loud

You trade control for battery: delivery timing belongs to Apple and Google, and payloads are small and visible to them, so sensitive content should be "you have a new message", not the message. The interviewer will ask how you avoid sending the same push twice when a worker crashes mid-batch, which is the idempotency key, and how you keep a chatty group from drowning a user, which is collapse keys plus per-user rate limits.

Where it shows up in the 100 Google problems

  • Design a notification system: this whole mechanism, generalised to email and SMS with per-channel workers, priorities and opt-outs.
  • Design a chat app: the push fires only when the recipient has no open socket, and collapses per conversation.
  • Personalized deals: millions of low-priority pushes scheduled into local morning hours and rate limited per user.
  • Design Google Calendar: reminders are scheduled jobs that turn into high-priority pushes at the right instant.
  • Job alerts for Google Careers: a daily batch that must notify each candidate once per matching posting.

02Used in these problems