Two options dominate email provider discussions for Next.js apps: Resend, with its React-native SDK, and Amazon SES, the AWS service that already powers a lot of transactional email on the internet (Resend included).
The short answer is easy. Sending under a few hundred thousand emails a month and want to be productive today? Resend. Sending millions and already living inside AWS? SES. The interesting part is the middle, which is where most Next.js teams actually sit.
~10x
Price gap at scale
SES is ~$0.10 per 1,000 emails. Resend is ~$1 per 1,000 on its paid tiers.
5 min
Resend setup time
Verify domain, paste API key, pass a React component to send().
IAM, SNS, SES
SES setup scope
Policies, sending identities, config sets, SNS for webhooks, and a Lambda to catch them.
TL;DR: which one should you pick?
Before the deep dive, here is the 30-second answer for common scenarios.
| If you are... | Pick | Why |
|---|---|---|
| Building a new Next.js SaaS | Resend | Native React Email support, fastest setup, clean DX. |
| Sending 1M+ emails per month | Amazon SES | At scale the ~10x price gap dominates everything else. |
| Already running on AWS with ops discipline | Amazon SES | Your team can absorb the IAM/SNS/CloudWatch overhead cheaply. |
| Solo dev or small team, first 100k emails | Resend | Time saved on plumbing outweighs the price difference. |
| Enterprise with AWS procurement and no new vendor budget | Amazon SES | One AWS line item beats a new vendor onboarding cycle. |
| You want optionality in 12 months | Resend now | Resend uses SES under the hood, so switching later keeps your deliverability intact. |
Most Next.js teams under ~1M sends/month should start with Resend.
Pricing head-to-head
Pricing is the most visible difference. SES is priced like infrastructure. Resend is priced like a developer tool. Here's what each actually costs at realistic volumes.
| Monthly volume | Amazon SES | Resend | Gap |
|---|---|---|---|
| 3,000 (hobby) | ~$0.00 (free tier eligible) | $0 (free plan) | tied |
| 50,000 | ~$5 | $20 (Pro) | $15 |
| 100,000 | ~$10 | $35 (Pro) | $25 |
| 500,000 | ~$50 | $90 (Scale) | $40 |
| 1,000,000 | ~$100 | ~$400 (custom) | $300 |
| 5,000,000 | ~$500 | Custom quote | Usually 5-10x |
Pricing is directional; check both sites for the latest. SES pricing excludes egress for attachments.
The dollars alone miss half the picture. At 50k-100k sends, the monthly markup is a rounding error next to the engineering hours you spend gluing SES together. Past ~1M sends, the gap gets big enough that a recurring ops hour pays for itself.
Developer experience for Next.js + React Email
This is where the gap is widest, and it's the main reason most Next.js teams end up on Resend even when the math leans slightly toward SES.
Sending with Resend
Resend was built by the React Email team. You pass a React component straight to the SDK.
import { Resend } from "resend";
import { WelcomeEmail } from "@/emails/welcome";
const resend = new Resend(process.env.RESEND_API_KEY!);
export async function POST(req: Request) {
const { email, name } = await req.json();
const { data, error } = await resend.emails.send({
from: "Acme <welcome@send.acme.com>",
to: email,
subject: "Welcome to Acme",
react: <WelcomeEmail name={name} />,
});
if (error) return Response.json({ error }, { status: 500 });
return Response.json({ id: data?.id });
}No HTML render step, no Handlebars compile, no string templating. The React component is the source of truth for what lands in the inbox.
Sending with Amazon SES
With raw SES, you render the email yourself and pass HTML (and, ideally, a plain-text alternative) to the SDK.
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses";
import { render } from "@react-email/render";
import { WelcomeEmail } from "@/emails/welcome";
const ses = new SESClient({ region: "us-east-1" });
export async function POST(req: Request) {
const { email, name } = await req.json();
const html = await render(<WelcomeEmail name={name} />);
const text = await render(<WelcomeEmail name={name} />, { plainText: true });
await ses.send(
new SendEmailCommand({
Source: "Acme <welcome@send.acme.com>",
Destination: { ToAddresses: [email] },
Message: {
Subject: { Data: "Welcome to Acme" },
Body: {
Html: { Data: html },
Text: { Data: text },
},
},
})
);
return Response.json({ ok: true });
}The code itself isn't awful. But before the call works, you need an IAM user or role with ses:SendEmail, a verified sending identity (domain or email address), and an account out of the SES sandbox. Multiply that friction by every engineer who onboards to the project.
- Pass React components directly to send()
- Domain verification is a copy-paste dashboard flow
- Webhooks (delivered, bounced, opened, clicked) signed out of the box
- Suppression list managed automatically
- Preview emails in a hosted dashboard per environment
- Free tier on day one (3,000 emails/month)
- Render React Email to HTML/text strings yourself
- Verify sending identities through the SES console or IaC
- Configure SNS topics + Lambdas (or SES event destinations) for webhooks
- Manage the SES suppression list via API calls
- Build your own preview UI on top of the SES sandbox
- Sandbox until AWS reviews and approves your account
Deliverability: closer than you'd expect
Because Resend sends through SES, both options share the same IP-level reputation. The AWS ranges Resend uses are the same ranges SES rents to every other customer. That baseline is hard to beat.
Where the two diverge is at the account level:
- Amazon SES will suspend your account if the bounce rate crosses 5% or complaint rate crosses 0.1%. Hygiene, suppression, and monitoring are on you.
- Resendhas the same caps but also auto-manages suppression and surfaces bounce/complaint rates in the dashboard. Fewer “you've been suspended” surprises on Monday morning.
Setup time: 5 minutes vs an afternoon
From a fresh Next.js project to a first live email, here's what each path looks like.
Resend: 5 minutes
- Sign up, add sending domain, copy three DNS records into your registrar
- Wait for DNS propagation (minutes, not hours)
npm install resend @react-email/components- Paste API key, write one React Email template, call
resend.emails.send
Amazon SES: an afternoon
- Create IAM user or role with
ses:SendEmail(or use Configuration Sets) - Verify sending identity (domain or email address)
- Publish DKIM CNAMEs, SPF, and
MAIL FROMdomain records - Submit sandbox-exit request, wait for AWS approval (hours to days)
- Stand up SNS topic + HTTPS subscription for bounce/complaint events
- Implement webhook verification, persistence, retry logic yourself
- Render React Email to HTML and plain text before each send
Both paths end with email in production. The difference is whether you spend your afternoon on product code or AWS glue.
Migration path: Resend now, SES later (if ever)
Since Resend already runs on SES, moving to raw SES later is mostly a code change, not a deliverability reset. DKIM/SPF still point at amazonses.com, domain reputation carries over, and spam filters see the same IP space. What you rewrite:
- The
resend.emails.sendcall becomes an AWS SDKSendEmailCommandorSendRawEmailCommand - Resend's signed webhooks become SNS subscriptions (or SES event destinations)
- Suppression list imports/exports
- Template render: add a
render()call from@react-email/renderbefore each send
Wrap your sends in a thin helper from day one (lib/email/send.ts) and the whole swap lives in one file.
FAQ
Resend vs AWS SES: which has better deliverability?
Effectively the same at the IP layer, because Resend uses SES. Account-level reputation management is more hands-on with SES and more managed with Resend.
When does the price gap actually matter?
Below ~500k emails/month, the dollar difference is small enough that engineering time dominates. Above 1M, the gap can fund a part-time ops hire. That's usually the threshold where teams move to SES direct.
Does Amazon SES support React Email?
Yes, via @react-email/render. You render the component to an HTML string (and a plain-text alternative) and pass that into the SES SDK. Resend skips the explicit render step.
How do bounce and complaint webhooks compare?
Resend ships signed webhooks you subscribe to from the dashboard. SES emits events to SNS; you forward those to an HTTPS endpoint or a Lambda. Both get you there. Resend gets you there in minutes.
What about the SES free tier?
The SES free tier (62,000 emails/month) only applies when sending from an EC2 instance. Next.js apps on Vercel, Netlify, or any other host pay ~$0.10 per 1,000 emails from message one.
Bottom line
For a typical Next.js SaaS, Resend is the right default. You get SES deliverability, React Email-native sends, signed webhooks, and a dashboard in minutes. And you keep a clean exit to raw SES if your volume ever justifies it.
The bigger lever on your email ROI isn't the provider anyway. It's the templates. Whether you pick Resend or SES, the next shortcut is skipping the week of hand-coding transactional templates:
Related reading: Does Resend use Amazon SES? and Resend vs SendGrid vs Amazon SES for Next.js.