All the parts

Build · Do it later

Notifications

How do I send email, push, text messages and in-app alerts?

What it is

Notifications are messages your app sends to people when something happens. You do not run your own mail or phone servers. You call a provider, and it delivers the message. Always send them from a background worker, not inside the user's request.

It is a post office: you hand over the letter and the address, and they handle the trucks.

Add it when Users must confirm an email, reset a password, get receipts or hear about activity.

It can wait when Nothing happens outside the page the user is looking at.

1 Which one should I pick?

Answer what you can. The ranking updates as you go, and you can ignore it if you disagree.

Which channel do you need first?
How many channels will you use?
What matters most right now?

Most people start with

2 Side by side

Three pips is strong, one is weak. Pick a row to read about it below.

OptionQuick to set upCheap while smallEasy to leaveRoom to growPrice
Free tier, then pay per email volume
Free
Pay per message, plus a number rental
Free tier, then pay per message or seat

3 Look closer, then wire it in

Managed service

Resend (or AWS SES)

Send email from your code with one API call. SES is the cheaper, rougher cousin.

Pick it when You need sign-up, receipt and reset emails that actually reach the inbox.

Skip it if You need push or text messages, since this is email only.

  • Simple API and clear docs
  • Works with React email templates
  • Shows delivery status
  • Email only
  • You must set up your domain records first
Quick to set up
Cheap while small
Easy to leave
Room to grow

PriceFree tier, then pay per email volume

How to connect it

  1. Create an account and add your domain.
  2. Add the DNS records it shows you (SPF and DKIM) and wait for it to verify.
  3. Create an API key and store it as a secret.
  4. Call the send method from a background job.
Put these in your .env file
  • RESEND_API_KEY
email.ts
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({
  from: "Acme <hello@yourdomain.com>",
  to: "user@example.com",
  subject: "Welcome",
  html: "<p>Thanks for signing up.</p>",
});

4 Watch it work

Press play, or step through one message at a time.

Press Play to watch it run · 7 steps

The signup request stays fast. A worker sends the message later through a provider.

From event to inboxThe signup request stays fast. A worker sends the message later through a provider.Event: user signed upJob: send welcome emailBuild the message from a templateSend from your verified domainAcceptedDeliver to the inboxWebhook: delivered or bounced
  • Service
  • Queue
  • Worker
  • External API
  • Client
Text description
  1. Your app → Queue: Event: user signed up
  2. Queue → Worker: Job: send welcome email
  3. Worker: Build the message from a template
  4. Worker → Email provider: Send from your verified domain
  5. Email provider replies to Worker: Accepted
  6. Email provider → User's device: Deliver to the inbox
  7. Email provider → Your app: Webhook: delivered or bounced

5 Mistakes to skip

  • Sending the email inside the signup request.

    Put a job on a queue and send from a worker. If the provider is slow, signup still feels instant.

  • Sending from an unverified domain.

    Add the SPF and DKIM records (DNS proofs that you own the domain) so inboxes trust you instead of using the spam folder.

  • Sending to every address without checking.

    Stop sending to addresses that bounce or complain, and add an unsubscribe link to non-essential mail.

See where it sits in a whole app

The stack builder draws your product with notifications in it and animates a request through it.

Open the stack builder

Works closely with