Web Push Use-Case Playbooks

Generic best practices only get you so far. The right urgency header, TTL, payload shape, and cadence differ wildly between a cart-abandonment nudge, a SaaS feature prompt, and a breaking-news alert. This reference walks product and marketing readers through three complete playbooks, links each to its dedicated build guide, and points to the technical guides that make each one work in production.

Problem statement

Most push programs apply one configuration to every message — the same TTL, the same urgency, the same frequency. That averages everyone’s experience into mediocrity. A breaking-news alert with a one-day TTL is useless; a cart reminder sent with urgency: high and a 10-second TTL arrives too late and too loud. Matching the message to the use case is the difference between a notification channel people keep and one they block. Each playbook below defines the right knobs for its job.

Prerequisites

How the three playbooks differ

The defining axes are urgency (how fast it must arrive), TTL (how long it stays relevant), and frequency (how often you send). Cart abandonment is moderately urgent, moderate TTL, low frequency per user. SaaS re-engagement is low urgency, long TTL, low and spaced frequency. Breaking news is maximally urgent, very low TTL, and potentially high fan-out frequency. Get these three right and the rest of the configuration follows.

A fourth, quieter axis is fan-out shape — whether a given message targets one user, a behavioral segment, or your entire base at once. It rarely gets discussed alongside the others, but it determines your infrastructure more than any header. A per-user trigger (cart abandonment) needs a reliable event pipeline and a modest send rate. A per-segment trigger (SaaS adoption) needs good targeting and a frequency cap. A whole-base broadcast (breaking news) needs a queue and worker pool that can absorb a burst of millions of sends without melting. Two campaigns can share identical urgency, TTL, and copy and still demand completely different backends because their fan-out shapes differ.

Fan-out shape by playbook A per-user trigger reaches one subscriber and needs an event pipeline; a per-segment trigger reaches thousands and needs targeting plus a frequency cap; a whole-base broadcast reaches millions and needs a queue and a worker pool. Fan-out shape decides the backend, not the copy Per-user trigger event 1 subscriber per send Cart abandonment Needs: a reliable event pipeline, modest send rate Per-segment trigger segment Hundreds to thousands SaaS re-engagement nudge Needs: accurate targeting plus a frequency cap Whole-base broadcast story Millions, near-simultaneous Breaking-news alert Needs: burst queue and a rate-limited worker pool Identical copy and headers, three different delivery architectures
Fan-out shape is the axis nobody discusses: it decides your queue, your worker pool and your rate budget.

The urgency header itself is worth understanding precisely. Defined in RFC 8030, it takes the values very-low, low, normal, and high, and it tells the push service how aggressively to deliver — whether to wake a sleeping device or hold the message for the next opportunistic wake-up. High urgency consumes device battery and user attention, so it is a finite resource: spend it on breaking news, conserve it on re-engagement. Misusing urgency is one of the fastest routes to a user disabling notifications entirely.

Urgency, TTL and frequency by use case Three rows compare cart abandonment, SaaS re-engagement and breaking news across urgency, TTL and frequency; bar lengths show relative emphasis rather than measured values. Urgency / TTL / frequency by use case Use case Urgency TTL Frequency Cart abandonment normal 3 h 1–2 per cart SaaS re-engagement low ~1 day ≤1 per week Breaking news high 5 min burst Bar length is relative emphasis, not an exact value Values shown are sane starting defaults, not measured results
Each playbook lives at a different point in the urgency / TTL / frequency space — which is why one configuration can't serve all three.

Playbook 1 — E-commerce cart abandonment

When a shopper adds items and leaves without checking out, a well-timed push recovers a sale that would otherwise evaporate. The mechanics: trigger on the abandonment event (cart inactive for a short window), carry a deep link straight back to the cart, choose a TTL measured in hours because the intent decays fast, and cap frequency to avoid feeling like surveillance. The payload must include the deep link and stay under the 4 KB limit with aes128gcm encoding, so the cart contents live behind the link, not in the notification.

The metric that matters is recovered revenue attributed through the deep link, not clicks — a click that doesn’t check out isn’t a recovery. The hardest constraint is the combination of timing and payload size: fire too soon and you interrupt a deciding shopper, too late and the sale is gone, and stuff product details into the payload and you blow past the size budget. The discipline is to send only an identifier and a deep link, then let the landing page render the cart.

The full build — trigger timing, payload construction, TTL choice, and the recovery sequence — is in the e-commerce cart abandonment push playbook. Because deep links and offer details ride in the encrypted payload, review push API payload encryption to keep them inside the size budget, and make sure your subscribe flow respects permission prompt timing so checkout-intent shoppers are actually opted in when you need to reach them.

Playbook 2 — SaaS user re-engagement

For SaaS, the goal is durable activation and adoption, not a single conversion. Pushes fire on lifecycle signals — an unreached activation milestone, an unadopted feature, a churn-risk drop in usage — rather than on a clock. These are low-urgency, long-TTL messages spaced generously so they read as helpful, not desperate. Frequency discipline is everything here: one well-targeted nudge a week beats five generic ones.

What separates good SaaS push from spam is that every message maps to a specific, fixable gap in the user’s journey rather than a calendar date. “You haven’t logged in for a week” is a blunt instrument; “you created a project but never invited a teammate” points at a concrete next action and a measurable outcome. That precision is also what lets you keep frequency low without losing impact — when each nudge is genuinely relevant, one a week outperforms five generic ones, and the user keeps notifications enabled.

The complete sequence — activation milestones, feature-adoption nudges, and churn-risk triggers — is in the SaaS user re-engagement push strategy. It builds directly on the broader re-engagement campaign strategies and shares its long-TTL stance from TTL and expiration handling.

Playbook 3 — Breaking-news alerts

Breaking news inverts every previous priority. The message is worthless minutes after the event, so it needs urgency: high, a very low TTL, and a topic (collapse key) so a correction supersedes the original rather than stacking. The hard part is scale: a single story can fan out to millions of subscribers in seconds, which is a throughput and queueing problem, not a payload problem.

The throughput math is sobering. If a story should reach two million subscribers within a minute, you need to sustain roughly 33,000 sends per second — well beyond what a single process or a naive loop can manage, and right up against the per-service rate limits that trigger 429 responses. The answer is to decouple the editorial trigger from delivery: one action enqueues a single fan-out job, and a pool of workers drains the queue in rate-limited batches, requeuing transient failures with backoff so a rate-limit spike never drops the audience. Speed is the product here; a late breaking-news alert is worse than none.

The architecture — high fan-out, low TTL, urgency header, topic/collapse keys, and throughput — is detailed in the breaking-news push alert architecture. Delivering it at scale leans on message batching and throughput optimization and a hardened retry and backoff layer.

Playbook comparison

Dimension Cart abandonment SaaS re-engagement Breaking news
Trigger Cart-inactive event Lifecycle milestone / churn risk Editorial event
Urgency header normalhigh low high
TTL Hours (e.g. 3,600–14,400 s) ~1 day (86,400 s) Minutes (e.g. 60–600 s)
Frequency per user Low (1–2 per cart) Spaced (≤ ~weekly) Event-driven
Fan-out Per-user Per-segment Massive, simultaneous
Collapse / topic key Optional (per cart) Optional Required
Primary metric Recovered revenue Reactivation / adoption Time-to-deliver, CTR
Hardest constraint Payload size + timing Frequency discipline Throughput at fan-out

Shared foundations across all three

However different the playbooks look, they rest on the same infrastructure, and getting that foundation right is a prerequisite for any of them. Three pieces matter most.

Payload discipline. Every playbook carries a deep link, not content. The encrypted ciphertext must stay under the 4 KB limit with the aes128gcm content encoding RFC 8291 requires, so product images, article bodies, and offer details all live on the landing page behind the link. This keeps payloads atomic and well under the size ceiling regardless of use case, and it means the notification’s only job is to get the user to tap through.

Credential hygiene. All three sign requests with VAPID, and in every case the public key must come from process.env.VAPID_PUBLIC_KEY (and the private key from process.env.VAPID_PRIVATE_KEY) — never hardcoded into server code or committed to version control. A leaked key invites push injection and forces an emergency rotation that risks your active subscriber base. The mechanics are covered in VAPID key generation and rotation.

Failure handling. Each playbook will see 410 Gone (prune the endpoint), 429 Too Many Requests (back off and retry), and occasional 5xx (transient — retry with backoff). Centralize this in one resilient send layer built on retry logic and backoff strategies so a cart reminder, a SaaS nudge, and a news alert all benefit from the same battle-tested error path rather than each reinventing it.

One shared send layer for all three playbooks Cart, SaaS and news campaigns all enter a single send layer that signs a VAPID JWT from environment variables, enforces the 4 KB aes128gcm payload budget and sets urgency, TTL and topic, then routes 201, 410 and 429 or 5xx responses to distinct outcomes. Three playbooks, one send path and one error path Cart trigger SaaS nudge News alert Shared send layer Sign VAPID JWT keys from env only Encrypt ≤ 4 KB aes128gcm, deep link Per-playbook knobs urgency · TTL · topic Push service HTTP response 201 Created accepted 410 Gone prune endpoint 429 / 5xx retry, backoff Switching playbook changes the knobs, never the send path
Payload discipline, credential hygiene and one hardened failure path are shared; only urgency, TTL and topic differ per playbook.

When these foundations are solid, switching between playbooks becomes a matter of changing three knobs — urgency, TTL, frequency — plus the trigger and fan-out shape, rather than rebuilding delivery from scratch.

Choosing a playbook

Start from the question the message answers for the user. “Did you forget something?” is cart abandonment. “Have you tried this yet?” is SaaS re-engagement. “This just happened” is breaking news. Each maps to a different urgency/TTL/frequency profile, and copying the wrong profile is the most common reason a push channel underperforms or gets blocked.

Choosing a playbook from the question the message answers One question branches three ways: did you forget something maps to cart abandonment with normal urgency and a three hour TTL, have you tried this yet maps to SaaS re-engagement with low urgency and a one day TTL, and this just happened maps to breaking news with high urgency and a five minute TTL. What does this message tell the user? “Did you forget something?” Cart abandonment urgency: normal TTL 3 h, topic per cart 1–2 touches per cart metric: recovered revenue “Have you tried this yet?” SaaS re-engagement urgency: low TTL ~86,400 s cap ≤1 per user per week metric: adoption lift “This just happened.” Breaking news urgency: high TTL 60–600 s topic per story, required metric: time-to-deliver Answer the question first; the headers follow from it
Route from the reader's question to the playbook, then take its urgency, TTL and topic settings as your starting defaults.

Verifying a Playbook Before It Reaches the Base

Every playbook here is a scheduled job that reads user state and sends on a trigger, which means the expensive failure is not a bad headline — it is a trigger that fires for the wrong cohort at full volume. Verify in three stages, and never let stage three be the first real test.

Stage one is a dry run against production data with sending disabled. Execute the selection query, write the resulting endpoint list and the rendered payload for each row to a table, and send nothing. Read the row count first: an order-of-magnitude surprise almost always means a join lost its date predicate. Then read ten payloads by hand, including one for a user with a null in every optional personalisation field, because that is the row that renders “Hi ,” and ships it. Confirm the encrypted body of the largest rendered payload fits the 4 KB aes128gcm ceiling — personalised strings are exactly where a payload crosses it, and the limit applies to the ciphertext, not your JSON.

Stage two is a seeded send to an internal cohort on real devices, one per platform you support. This is the only stage that catches rendering and click-routing problems, because they live in the platform rather than your code: verify the notification appears with the icon and body you expect, that a click lands on the deep link rather than the site root, and that the click event arrives in your analytics with the campaign identifier attached. Do this on a locked phone as well as an unlocked one — the collapse and grouping behaviour differs, and a campaign that reads well in a desktop tray can be truncated to uselessness in an Android system row.

Stage three is a ramped release: one percent of the eligible cohort, then ten, then the remainder, with a hold between steps long enough to see the guardrail metrics move. Watch the unsubscribe rate and the permission-revocation rate, not the click-through rate — click-through tells you whether the copy worked, while those two tell you whether you are damaging the asset. A ramp also bounds the blast radius of the failure mode no dry run catches: a trigger that is correct on today’s data and wrong on tomorrow’s.

-- Stage one: materialise the cohort and the payload, send nothing.
INSERT INTO campaign_dryrun (run_id, endpoint_hash, payload, payload_bytes)
SELECT :run_id,
       s.endpoint_hash,
       p.payload,
       octet_length(p.payload) AS payload_bytes
FROM   eligible_cohort(:campaign, :as_of) c
JOIN   subscriptions s ON s.user_id = c.user_id AND s.state = 'active'
CROSS JOIN LATERAL render_payload(:campaign, c.user_id) AS p(payload);

-- Then read these three numbers before anyone approves a send.
SELECT count(*)                    AS recipients,
       max(payload_bytes)          AS largest_payload,
       count(*) FILTER (WHERE payload LIKE '%Hi ,%') AS broken_personalisation
FROM   campaign_dryrun WHERE run_id = :run_id;

Keep the dry-run table. When a campaign underperforms, the question is almost always “who actually received this?”, and a stored cohort snapshot answers it in one query instead of a reconstruction from logs that have since rotated.

One classification question sits above all three: is this message a fact the user asked for, or an offer you decided to send? A shipping update and a flash sale need different queues, different frequency-cap treatment and a different legal basis for sending, which is why the split between transactional and marketing push notifications is worth settling before you tune a single header. Cart and SaaS nudges are marketing by that test even when they look helpful; an order receipt fired from the same e-commerce stack is not.

FAQ

Can I use the same TTL for every campaign type?

No — TTL should match how fast the message’s value decays. Breaking news needs a TTL of minutes so a stale alert is dropped rather than delivered late; cart abandonment lives for a few hours; SaaS re-engagement can buffer for about a day. A single TTL either drops messages that should persist or delivers ones that should have expired.

What is a collapse (topic) key and which playbook needs it most?

A topic/collapse key lets a newer message replace an undelivered older one with the same key, so a device that was offline receives only the latest. Breaking news needs it most: a correction or update should supersede the original alert rather than land as a second notification. Cart abandonment can use it per cart to avoid stacking reminders.

Which playbook is hardest to scale?

Breaking news, by a wide margin. Cart and SaaS messages fan out per user or per segment, but a breaking story can require millions of simultaneous sends, making throughput and queueing the dominant constraint. That’s why its architecture leans on batching and a resilient retry layer rather than on payload tuning.

Where do order receipts and other transactional sends fit?

They sit outside all three playbooks and belong on their own pipeline. A receipt is a fact the user’s own action produced, so it is exempt from frequency caps and quiet hours and rests on a different legal basis from a promotion. Route it through a separate low-latency queue rather than reusing a campaign playbook’s knobs.