Nodemailer has 5.2 million weekly npm downloads and has been the standard for Node.js email since 2010. Resend has 500K weekly downloads but launched only in 2022 and is growing fast. The comparison isn't just about downloads — it's about what you're actually getting. Nodemailer is a transport layer; it connects to an SMTP server but the deliverability, IP reputation, and infrastructure are entirely your responsibility. Resend is a managed email API where deliverability is handled for you. Different tools for different problems.
Nodemailer is an SMTP client library for Node.js. It connects to any SMTP server — Gmail, SendGrid, Mailgun, your own Postfix server — and sends emails through it. What it is NOT: it's not an email delivery service. Nodemailer doesn't have servers, doesn't manage IP reputation, doesn't handle bounces, and doesn't provide analytics. If you use Nodemailer with Gmail's SMTP, you're limited to 500 emails/day and are subject to Gmail's spam filters. If you use it with a fresh VPS-hosted Postfix server, your emails probably land in spam on day one.
Resend's DX is genuinely excellent. The SDK is TypeScript-first with a clean API — one function call, returns a promise. Native React Email integration lets you write email templates as React components — JSX in your emails with real component composition and TypeScript safety. No template string interpolation, no HTML escaping issues. For a Next.js developer already thinking in React components, this workflow is natural. Setting up Resend from zero to first sent email takes under an hour.
Nodemailer (SMTP client) Resend (managed API)
──────────────────────── ─────────────────────────
Your App Your App
│ │
▼ ▼
Nodemailer createTransport() resend.emails.send({
│ from: 'hello@yourdomain.com',
▼ to: user.email,
SMTP Server (your choice): react: <WelcomeEmail name={name} />,
├── Gmail: 500/day limit })
├── AWS SES: $0.10/1k (cheap)
├── Your Postfix: IP reputation? Resend handles:
└── SendGrid: requires setup ├── IP reputation (managed)
├── SPF/DKIM/DMARC
npm downloads (2025): ├── Bounce processing
Nodemailer: 5.2M/week ├── Complaint handling
Resend: 500K/week (growing fast) └── Analytics dashboard
Pricing comparison:
Resend: $0.40/1k emails (free tier: 3k/month)
SES: $0.10/1k emails (but: your infrastructure)
Postmark: $1.50/1k emails (premium deliverability)
Gmail: Free but 500/day cap → breaks in productionFrom integrating Resend in a production SaaS: use React Email for all transactional email templates, even simple ones. The component model pays dividends when you need to update branding — change one EmailLayout wrapper and every template updates. With Nodemailer + raw HTML templates, brand updates require touching every template file. The React Email preview server (email.dev) also makes iterating on templates dramatically faster.
Email deliverability is complex — inbox placement depends on sending IP reputation, domain authentication (SPF, DKIM, DMARC), engagement metrics, and complaint rates. Resend (and other managed providers like Postmark and SendGrid) maintain warm sending IPs with established reputations, handle bounce and complaint processing automatically, and provide domain authentication setup guidance. When you use Resend, you inherit their IP reputation — for a new product, this is significantly better than a fresh IP.
# Install
npm install resend @react-email/components
# emails/WelcomeEmail.tsx (React Email component)
import { Html, Head, Body, Container, Text, Button } from "@react-email/components"
export function WelcomeEmail({ name, loginUrl }: { name: string; loginUrl: string }) {
return (
<Html>
<Head />
<Body style={{ fontFamily: "Inter, sans-serif", backgroundColor: "#f4f4f5" }}>
<Container style={{ maxWidth: "560px", margin: "40px auto", padding: "40px", backgroundColor: "#fff", borderRadius: "12px" }}>
<Text style={{ fontSize: "24px", fontWeight: "bold" }}>Welcome, {name}!</Text>
<Text>Your account is ready. Click below to log in.</Text>
<Button href={loginUrl} style={{ backgroundColor: "#3b82f6", color: "#fff", padding: "12px 24px", borderRadius: "8px" }}>
Log In Now
</Button>
</Container>
</Body>
</Html>
)
}
# app/api/send-welcome/route.ts
import { Resend } from "resend"
import { WelcomeEmail } from "@/emails/WelcomeEmail"
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: "Matthews Wong <hello@matthewswong.com>",
to: email,
subject: "Welcome to the platform",
react: <WelcomeEmail name={name} loginUrl="https://app.example.com/login" />,
})
if (error) return Response.json({ error }, { status: 500 })
return Response.json({ id: data?.id })
}
# Local development with Nodemailer + Ethereal (no real emails sent)
import nodemailer from "nodemailer"
const testAccount = await nodemailer.createTestAccount()
const transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
auth: { user: testAccount.user, pass: testAccount.pass },
})
const info = await transporter.sendMail({ ... })
console.log("Preview URL:", nodemailer.getTestMessageUrl(info))Resend's free tier covers 3,000 emails/month. Paid tiers start at roughly $0.40 per 1,000 emails. AWS SES via Nodemailer charges $0.10 per 1,000 emails — four times cheaper — but requires your own domain warm-up, bounce handling, SNS notification setup, and ongoing maintenance. For a product team focused on building features, the managed deliverability at $0.40/1,000 is usually worth it. For high-volume transactional email (millions/month), AWS SES becomes more attractive despite the infrastructure overhead.
Google limits Gmail SMTP to 500 emails/day for free accounts and 2,000/day for Google Workspace. More critically, Google aggressively rate-limits and blocks SMTP connections they deem suspicious. Your password-reset emails will start failing randomly as you scale. Gmail SMTP is acceptable for local development and testing. For production, use a dedicated transactional email API or at minimum a proper SMTP relay like Amazon SES, Mailgun, or SendGrid. The debugging time you'll spend on Gmail SMTP delivery failures exceeds the cost of any managed provider.
Nodemailer remains the right choice in specific scenarios: (1) You control an SMTP server (internal mail relay, Postfix on your infrastructure) and need to connect to it programmatically. (2) You're building an email testing workflow that catches outgoing email locally — combine Nodemailer with Ethereal.email or Mailhog for zero-cost local email testing. (3) You have a high-volume sending scenario and want AWS SES at $0.10/1,000 with direct SMTP access rather than an API client. In all other cases, a managed API (Resend, Postmark, Mailgun) provides better DX and deliverability.
I use Resend for all new projects. The React Email integration is the decisive factor — writing email templates as React components with TypeScript is genuinely better than managing HTML strings or template files. Resend's free tier is sufficient for early-stage projects (3,000 emails/month covers most side projects and early SaaS products), and the API is so simple that email integration takes an afternoon rather than a day. I reserve Nodemailer for local development testing with Ethereal.email — it's the best way to test email flows without hitting real SMTP limits.
Install: npm install resend @react-email/components. Set RESEND_API_KEY in your environment. Create a Route Handler or Server Action that calls resend.emails.send() with your React Email template as the react property. Verify your sending domain in the Resend dashboard (add the DKIM/SPF records they provide to your DNS). Done. The entire integration is ~20 lines of code plus your email template component. Compare that to a Nodemailer + AWS SES setup which requires IAM roles, SES domain verification, bounce/complaint SNS topics, and a custom transport configuration.