Skip to main content

Resend vs SendGrid vs Postmark

·APIScout Team
resendsendgridpostmarktransactional-emailreact-emailemail-api2026

TL;DR

Resend for new projects — developer DX is best, React Email integration is native, generous free tier. Postmark for transactional email when deliverability is non-negotiable — they've maintained industry-leading inbox placement rates for 15 years. SendGrid for high-volume (1M+ sends) where cost matters and you're okay with a more complex API. In 2026, Resend has largely won the developer mindshare but Postmark's reputation still matters for apps where "password reset went to spam" is catastrophic.

Key Takeaways

  • Resend: $0 free (3K/month), best DX, React Email native, $20/month (50K sends)
  • Postmark: $15/month (10K sends), #1 deliverability, best for transactional-only use cases
  • SendGrid: $20/month (100K sends), most features, complex API, used by large enterprises
  • Deliverability: Postmark > Resend ≈ SendGrid for inbox placement rates
  • React Email: all three support HTML/text, but Resend's SDK has first-class React Email integration
  • Volume pricing: SendGrid cheapest at >100K sends/month; Resend most expensive

Resend: Developer-First Email

Best for: indie developers, SaaS builders, anyone using React for email templates

// npm install resend
import { Resend } from 'resend';

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

// Send a plain HTML email:
const { data, error } = await resend.emails.send({
  from: 'Acme <noreply@acme.com>',
  to: ['user@example.com'],
  subject: 'Welcome to Acme!',
  html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
  text: 'Welcome! Thanks for signing up.',  // Plain text fallback
});

React Email Integration (Killer Feature)

// npm install @react-email/components react react-dom
// emails/welcome.tsx:
import {
  Html,
  Head,
  Preview,
  Body,
  Container,
  Heading,
  Text,
  Button,
  Hr,
} from '@react-email/components';

interface WelcomeEmailProps {
  userName: string;
  loginUrl: string;
}

export function WelcomeEmail({ userName, loginUrl }: WelcomeEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Welcome to our platform, {userName}!</Preview>
      <Body style={{ fontFamily: 'Arial, sans-serif', backgroundColor: '#f4f4f4' }}>
        <Container style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
          <Heading>Welcome, {userName}! 👋</Heading>
          <Text>Thanks for signing up. Here's how to get started:</Text>
          <Button
            href={loginUrl}
            style={{
              backgroundColor: '#000',
              color: '#fff',
              padding: '12px 24px',
              borderRadius: '4px',
              textDecoration: 'none',
            }}
          >
            Get Started →
          </Button>
          <Hr />
          <Text style={{ color: '#666', fontSize: '12px' }}>
            You received this because you signed up at acme.com.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}
// Send React Email with Resend:
import { render } from '@react-email/render';
import { WelcomeEmail } from '@/emails/welcome';

const emailHtml = render(WelcomeEmail({ userName: 'Alice', loginUrl: 'https://acme.com/login' }));

await resend.emails.send({
  from: 'Acme <noreply@acme.com>',
  to: [user.email],
  subject: 'Welcome to Acme!',
  html: emailHtml,
});
// Resend batch sending:
const { data } = await resend.batch.send([
  {
    from: 'noreply@acme.com',
    to: 'user1@example.com',
    subject: 'Your weekly report',
    html: render(WeeklyReport({ user: user1 })),
  },
  {
    from: 'noreply@acme.com',
    to: 'user2@example.com',
    subject: 'Your weekly report',
    html: render(WeeklyReport({ user: user2 })),
  },
]);

Resend Pricing

Free:          3,000 emails/month, 1 domain
Pro ($20/month): 50,000 emails/month, unlimited domains
Scale ($90/month): 300,000 emails/month

Beyond plan limits (Pro overage):
  $1.50/1,000 emails = $0.0015/email

vs Postmark:   $0.001/email
vs SendGrid:   $0.0008/email at 100K

Postmark: Deliverability Champion

Best for: password resets, payment receipts, security alerts — any email that MUST reach the inbox

// npm install postmark
import * as postmark from 'postmark';

const client = new postmark.ServerClient(process.env.POSTMARK_API_TOKEN!);

// Send transactional email:
const response = await client.sendEmail({
  From: 'noreply@acme.com',
  To: 'user@example.com',
  Subject: 'Reset your password',
  HtmlBody: '<h1>Reset Your Password</h1><p>Click <a href="{{url}}">here</a>.</p>',
  TextBody: 'Reset your password: {{url}}',
  ReplyTo: 'support@acme.com',
  MessageStream: 'outbound',  // Or a named stream (e.g., 'password-resets')
});

console.log('Message ID:', response.MessageID);
// Postmark with templates (stored in dashboard):
await client.sendEmailWithTemplate({
  From: 'noreply@acme.com',
  To: user.email,
  TemplateAlias: 'welcome',  // Template created in Postmark dashboard
  TemplateModel: {
    product_name: 'Acme',
    name: user.name,
    action_url: `https://acme.com/verify?token=${token}`,
    support_email: 'support@acme.com',
  },
});

Message Streams

Postmark's key architectural feature — separate streams for transactional vs broadcast:

// Separate streams prevent marketing blocks from affecting transactional delivery:

// Transactional stream (highest priority, no unsubscribe required):
await client.sendEmail({
  From: 'noreply@acme.com',
  To: user.email,
  Subject: 'Payment receipt',
  HtmlBody: receiptHtml,
  MessageStream: 'outbound',  // Default transactional stream
});

// Broadcast stream (requires unsubscribe link):
await client.sendEmail({
  From: 'newsletter@acme.com',
  To: user.email,
  Subject: 'Monthly newsletter',
  HtmlBody: newsletterHtml,
  MessageStream: 'newsletters',  // Separate broadcast stream
});

Postmark Pricing

No free plan (100 test emails/month for devs)
$15/month:   10,000 emails
$45/month:   100,000 emails
$225/month:  1,000,000 emails

Per email at scale:
  100K:  $0.00045/email
  1M:    $0.000225/email

SendGrid: High-Volume Enterprise

Best for: 500K+ emails/month, marketing + transactional combined, existing SendGrid infrastructure

// npm install @sendgrid/mail
import sgMail from '@sendgrid/mail';

sgMail.setApiKey(process.env.SENDGRID_API_KEY!);

// Send email:
await sgMail.send({
  to: 'user@example.com',
  from: 'noreply@acme.com',
  subject: 'Welcome!',
  html: '<h1>Welcome!</h1>',
  text: 'Welcome!',
});
// Dynamic templates (HTML + substitutions):
await sgMail.send({
  to: user.email,
  from: 'noreply@acme.com',
  templateId: 'd-abc123',  // Template ID from SendGrid
  dynamicTemplateData: {
    first_name: user.firstName,
    reset_url: resetUrl,
  },
});
// SendGrid Inbound Parse (receive emails via webhook):
// When a user replies to your email, SendGrid POSTs to your webhook:
export async function POST(request: Request) {
  const formData = await request.formData();
  const from = formData.get('from') as string;
  const subject = formData.get('subject') as string;
  const text = formData.get('text') as string;

  // Handle reply email
  await processReply({ from, subject, text });
  return new Response('OK');
}

SendGrid Pricing

Free: 100 emails/day forever
Essentials ($20/month): 100K emails/month
Pro ($90/month): 1M emails/month
Premier: Custom

Per email at scale:
  100K:  $0.0002/email
  1M:    $0.00009/email

SendGrid is ~4x cheaper than Resend at 100K emails.
But has more moving parts (suppression groups, event webhooks, template engine).

Side-by-Side Comparison

ResendPostmarkSendGrid
Free tier3K/month100/month100/day
DeliverabilityGoodBestGood
DX (API quality)BestGoodComplex
React Email nativePartial
Templates in dashboardBasic
Marketing emailBroadcasts
Inbound email
Webhooks
100K/month cost~$90~$45~$20
Rate limit default2 req/sNoneNone

Recommendation

New SaaS (small to medium scale):
  → Use Resend
  → React Email templates, minimal config
  → Upgrade path exists (Scale plan for growth)

Established app where inbox placement is critical:
  → Use Postmark for transactional
  → Add SendGrid if you need marketing email
  → Message Streams = clean separation

High-volume or existing SendGrid users:
  → Stick with SendGrid
  → Cost savings significant at >500K emails/month
  → Complex API but worth it at scale

Compare all email APIs at APIScout.

Comments