Every product that lets people sign in has to send email a user is waiting on: the password reset, the magic link, the receipt, the "your export is ready." Get it wrong and support tickets arrive before the feature does. In 2026 the real shortlist is three services, and they don't compete on the same axis — Resend optimizes for developer experience, Postmark for deliverability, Amazon SES for cost at scale. Pick the axis that would hurt most to lose.

If you read one line: ship your first product on Resend, move to Postmark if a slow password-reset email costs you the customer, and switch to Amazon SES only when your volume makes its ~10x-cheaper per-email price worth the bounce-handling you'll build yourself.

The free tier decides your first six months#

For a team of one at day zero, Resend's free tier is the one that lets you not think about email for a while.

Price at scale, and the hidden line item#

At 100,000 emails a month the sticker prices split hard: SES lands near $10, Resend near $20–35, Postmark $100+. SES looks like the obvious win — until you read what the $0.10 per 1,000 buys. It's raw infrastructure. You build bounce handling, complaint handling, and reputation warming; you wire the SNS notifications into your own code and stay on call for them. Resend and Postmark do all of that for you. So the true cost of SES is the per-email price plus the engineering time to run it — which only pays off once volume is high.

The send code#

Resend — the reason people call it the best DX. Install resend, one call:

import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({
  from: "you@yourdomain.com",
  to: "user@example.com",
  subject: "Reset your password",
  html: "<p>Click <a href='https://app/x'>here</a> to reset.</p>",
});

Postmark — same shape, with a MessageStream so transactional never mixes with bulk:

import { ServerClient } from "postmark";
const client = new ServerClient(process.env.POSTMARK_TOKEN);

await client.sendEmail({
  From: "you@yourdomain.com",
  To: "user@example.com",
  Subject: "Reset your password",
  HtmlBody: "<p>Click <a href='https://app/x'>here</a> to reset.</p>",
  MessageStream: "outbound",
});

Amazon SES — the AWS SDK, and note there's no built-in bounce feedback here; you subscribe an SNS topic separately and handle the events yourself:

import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
const ses = new SESv2Client({ region: "us-east-1" });

await ses.send(new SendEmailCommand({
  FromEmailAddress: "you@yourdomain.com",
  Destination: { ToAddresses: ["user@example.com"] },
  Content: {
    Simple: {
      Subject: { Data: "Reset your password" },
      Body: { Html: { Data: "<p>Click <a href='https://app/x'>here</a> to reset.</p>" } },
    },
  },
}));

The decision, in one pass#

Start on Resend. You can move later — the send code is four lines and swapping providers is an afternoon. What you can't undo is a launch spent building SNS plumbing instead of the product. For where this fits in the rest of a founder's stack, see Resend as an email channel for AI agents and our tool highlight on Resend.