Blog · Product

Push notifications or email: when to use each channel

Push for what is urgent and short, email for what people must keep. A decision table by use case and two patterns to combine both channels without duplicates.

Leer en español

Use push notifications for messages that are short, urgent and lose their value within hours, and email for anything people need to keep, read at leisure or receive even when they have no subscribed device. Most products need both channels; what matters is deciding, message by message, which one carries it, and not sending the same thing twice without a reason.

In short:

  • A push reaches one specific browser that granted permission; an email reaches a person on any device.
  • Pick push when the message is useless tomorrow and asks for a quick action now.
  • Pick email for invoices, password resets, long content and notices that must exist in writing.
  • Combine them with rules: push when the user has active devices, email as a fallback or a record.
  • Misusing push is expensive: revoking permission turns off the whole channel in one click.

What actually separates the two channels

The real difference is not the format but the recipient. A push subscription identifies a browser on a device: someone who uses your product on a laptop and a phone may have two subscriptions, one, or none. An email address identifies a person and follows them to any device. Almost every other difference comes from that.

AspectWeb push notificationEmail
RequirementBrowser permission; on iPhone and iPad the site must also be added to the Home Screen (iOS 16.4 or later)A valid address
SizeShort title and body; the standard guarantees at least 4096 bytes of encrypted payloadLong, formatted, with attachments
LifespanGone once tapped or dismissedStays in the inbox, searchable and archivable
TimingSeconds if the device is online; otherwise it waits for as long as the TTL allowsWhenever the person checks their mail
Opt-outA switch in browser settings; you only find out on your next sendAn unsubscribe link, usually per message type

Look at the last row. With email, people usually unsubscribe from one kind of message and keep the rest. With push, a frustrated user revokes the permission and you lose every notification to that browser at once, including the useful ones.

When push notifications win

Push wins when the message expires quickly and the action it asks for fits in a single tap. A good test: if this notification arrived tomorrow morning, would it still be useful? If not, it is a strong push candidate.

  • Messaging and collaboration: someone replied in a thread or mentioned you in a document.
  • Live order status: "Your order just left the warehouse" or "Your courier is 5 minutes away".
  • Operational alerts: a deploy failed or an uptime check detected an outage.
  • Imminent reminders: "Your appointment starts in 30 minutes".
  • Time-boxed changes: a saved item dropped in price and stock is running low.

In all of these cases, set the message lifetime so it never shows up after it stops making sense. Our guide to TTL and urgency in web push covers how.

When email wins

Email wins when the message has to last, run long or prove something. Nobody digs through their notification center for an invoice from three months ago, and a push cannot verify identity.

  • Records and documents: invoices, receipts, contracts, updates to your terms.
  • Identity checks: confirming an address or resetting a password. The point is to prove the person controls that inbox, and a push proves nothing of the kind.
  • Long content: newsletters, weekly digests, reports with tables or many links.
  • Users without a subscription: anyone who never granted permission, uses an unsupported browser or has an iPhone without your site installed. On iOS and iPadOS, web push only works for sites added to the Home Screen, as WebKit's announcement explains.

There is also a privacy angle: push text can appear on the lock screen. Keep amounts, codes and personal data out of the title and body; use the push as a pointer ("You have a new payment") and keep the details behind sign-in.

A decision table by use case

Here is how we would route the most common messages. It is not a universal rule, but it is a useful starting point for reviewing your product's notifications one by one.

MessageChannelWhy
New chat messagePush; email only as a digest if still unread hours laterLoses value fast
Order shippedBothPush in the moment; email with tracking as the record
Password resetEmail onlyProves control of the inbox
Monthly invoiceEmail onlyA document people must keep
Price drop with limited stockPushShort window, one-tap action
Sign-in from a new deviceBothUrgent, and worth keeping on record
Weekly activity digestEmailLong and not urgent

How to combine them without duplicate alerts

The most useful pattern is routing by availability: before notifying, check whether the person has any active subscribed device. If they do, send a push; if not, send an email. With castly you can list subscribers filtered by your own user ID and then send to the users target, which reaches all of that person's devices. The parameters are in the API reference.

const API = 'https://castly.sh/v1';
const headers = {
  Authorization: `Bearer ${process.env.PUSH_SECRET_KEY}`,
  'Content-Type': 'application/json',
};

async function notify(user, msg) {
  const res = await fetch(
    `${API}/subscribers?userId=${encodeURIComponent(user.id)}&status=active&limit=1`,
    { headers }
  );
  const { data } = await res.json();
  if (data.length === 0) return sendEmail(user.email, msg); // your email provider

  await fetch(`${API}/notifications`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      to: { type: 'users', userIds: [user.id] },
      title: msg.title,
      body: msg.body,
      url: msg.url,
    }),
  });
}

The second pattern is push first with an email fallback: if nobody has tapped the notification after a few hours, send the email. castly does not send email or schedule sends, so the timer lives in your backend: store the send, listen for the notification.clicked webhook to mark it as seen, and have a job check the ones still pending later. Webhooks are best effort and not retried, so a missed click event can cause one extra email; for low-stakes messages that is an acceptable cost.

Finally, let people choose. A preferences page with categories ("activity on my team", "product news") and a channel per category reduces opt-outs on both sides.

Frequently asked questions

Can push notifications replace email in my product?

Not entirely. Push cannot reach people who are not subscribed, leaves no lasting record and cannot verify identity. It can, however, replace many short, urgent emails that currently get lost in the inbox.

What happens if the device is off when I send the push?

The push service holds the message for the TTL you set and delivers it when the device reconnects. If the TTL runs out first, the message is dropped and you are not told. Email, by contrast, waits in the inbox indefinitely.

Should I send the same alert on both channels at once?

Only when immediacy and a record both matter, as with a security alert or a shipped order. Otherwise duplication just adds noise and nudges people to switch one of the channels off.

Which channel gets a higher click-through rate?

There is no universal figure that holds across products, so be wary of generic comparisons. Measure your own notifications; for push, divide clicks by delivered notifications, as explained in how to measure push click-through rate.

Do I need separate consent for each channel?

Browser permission is the technical requirement for push and is requested on its own. The legal basis for marketing messages depends on your jurisdiction and does not carry over from one channel to another, so review it for each.

Put it into practice with castlyWeb and PWA push notifications for developers: an SDK under 3 KB, a REST API and delivery logs for every device. Free up to 10,000 pushes a month.
Create a free account →

Send your first push notification today.

Create a project, add the SDK and send with one API call. Free to start.

Create a free account →