Skip to content

Backend

Resend vs SendGrid vs Postmark — Transactional Email That Actually Lands

All articles
📨 ✉️

SendGrid won by bundle bloat. Postmark by price tag. Resend won by doing one thing right: sending email your customers actually see.

Transactional email is the backbone of SaaS: order confirmations, password resets, invoice delivery, onboarding flows. It's also where 90% of indie builders ship garbage. They pick SendGrid because it's famous, get lost in marketing dashboards and template builders they'll never use, and then wonder why emails land in spam. Or they pick Postmark, love the onboarding, and then choke when bills hit $2k/month at 500k emails. Resend flipped the game: clean Node.js API, React Email templates you write in JSX (not drag-and-drop), 50k free emails per month, $20/mo for 50k more, and zero dashboard theatre. Velocity X ships Resend by default. Here's the pricing breakdown, API DX comparison, and the real code that makes it work.

Pricing: The Hidden Story

Numbers lie unless you dig into the detail.

SendGrid: Free tier gives 100 emails/day (3k/month). Starter is $30/mo for 15k emails. Enterprise starts at custom quotes. Sounds cheap until you hit volume — they charge per email segment, per-template version, per A/B test report. The "free marketing tools" are intentional: lock you in at the free tier, you get comfortable with their UI, then upgrade features slowly and the bill creeps to $300+/month. Real indie builders spend 4x the stated tier price.

Postmark: Transparent pricing. 100 emails/month free. $10/10k emails (so $100 for 100k, $1k for 1M). Sounds ideal — and it is, right until you're doing 500k emails/month for a maturing product. At that scale, you're paying $5k/month. Postmark's actual win is their support and deliverability reputation (they run boring, boring infrastructure), not the price.

Resend: 50k emails free per month. Then $20/month for 50k more (so $20 gets you to 100k). $40 for 150k. The math is clean: $0.0004/email after free tier, flat-rate monthly. At 500k emails, you're spending $200/month. At 5M, you're spending $2k. Velocity uses Resend because the pricing scales with product growth, not against you.

Cost comparison at key volumes:

Volume      SendGrid    Postmark    Resend
10k/mo      ~$30        $10         $0 (free)
100k/mo     ~$100       $100        $20
500k/mo     ~$300-600   $500        $200
2M/mo       ~$1200      $2000       $800

API & Developer Experience

This is where Resend pulls ahead. SendGrid's API is verbose and empire-building. Postmark's is clean but you're still thinking in "email provider" terms. Resend's API reads like you're shipping a feature, not wiring a third-party service.

SendGrid setup: install `@sendgrid/mail`, create a mail helper, construct a message object with fields, send it, handle responses, manage templates in their dashboard. Templates are JSON blobs. You're context-switching to the SendGrid UI to tweak copy.

Postmark setup: similar — install `postmark`, construct a message, send, manage templates on their site. Clean API but still feels like you're driving a service, not shipping a feature.

Resend: install `resend`, write your email in React, send it. That's it. Templates are JSX components. You update copy in your repo. Here's real code from a Velocity X onboarding flow:

// lib/emails/WelcomeEmail.tsx
import React from 'react';
import {
  Body,
  Container,
  Head,
  Heading,
  Html,
  Preview,
  Section,
  Text,
} from '@react-email/components';

export const WelcomeEmail = ({ userName, setupLink }: any) => (
  <Html>
    <Head />
    <Preview>Welcome to Velocity, {userName}</Preview>
    <Body style={{ backgroundColor: '#f3f4f6' }}>
      <Container style={{ backgroundColor: '#ffffff', padding: '20px' }}>
        <Heading>Welcome to Velocity, {userName}</Heading>
        <Text>
          Your account is ready. Complete setup in 2 minutes to unlock all features.
        </Text>
        <Section style={{ marginTop: '20px' }}>
          <a href={setupLink} style={{
            backgroundColor: '#6366f1',
            color: '#fff',
            padding: '10px 20px',
            borderRadius: '4px',
            textDecoration: 'none'
          }}>
            Start Setup
          </a>
        </Section>
        <Text style={{ marginTop: '20px', fontSize: '12px', color: '#666' }}>
          Questions? Reply to this email.
        </Text>
      </Container>
    </Body>
  </Html>
);

// netlify/functions/send-welcome.ts
import { Resend } from 'resend';
import { WelcomeEmail } from '../../lib/emails/WelcomeEmail';

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

export default async (event: any) => {
  const { email, userName } = JSON.parse(event.body);

  try {
    const result = await resend.emails.send({
      from: 'Velocity <onboarding@velocity9.dev>',
      to: email,
      subject: `Welcome, ${userName}`,
      react: WelcomeEmail({ userName, setupLink: 'https://app.velocity9.dev/setup' }),
    });

    return {
      statusCode: 200,
      body: JSON.stringify({ success: true, messageId: result.data?.id }),
    };
  } catch (err: any) {
    console.error('Email send failed:', err.message);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: err.message }),
    };
  }
};

Notice: no template management UI. Update copy, redeploy, done. Components compose — build a Header, Footer, Button, reuse them across 50 emails. Test emails locally before shipping. This is how a modern email stack works.

Deliverability: DKIM, SPF, DMARC

Email lands in spam for one reason: authentication headers fail. SendGrid, Postmark, Resend all support DKIM signing (they sign on your behalf so your domain is verified as the sender). But setup is where people choke.

DKIM (DomainKeys Identified Mail): Signing proves you own the domain. Resend gives you two DKIM records to add to your DNS. Add them (takes 5 minutes), verify, and Resend signs every email with your domain's private key. Receivers trust your email because cryptography says it came from your domain, not a spoofed sender.

SPF (Sender Policy Framework): Tells receivers which servers are allowed to send email on your behalf. You add a single DNS record: `v=spf1 include:resend.com ~all`. This says "only Resend's servers can send mail from this domain."

DMARC (Domain-based Message Authentication, Reporting and Conformance): The enforcement layer. You set DMARC policy to `p=quarantine` (flag suspicious mail) or `p=reject` (hard block spoofed mail). Before you set this, make sure SPF and DKIM are working — test with `mail-tester.com` first.

Resend's setup guide walks you through this. SendGrid's does too, but you have to navigate their bloated dashboard. Postmark's is excellent. The difference: Resend makes it so simple that indie builders actually do it. SendGrid has a "Sender Authentication" page buried under three menu layers — most devs never find it. Broken DKIM = spam folder, always.

React Email: The Template Game-Changer

React Email is Resend's secret weapon. It's open source (you can use it standalone), but Resend integrates it so cleanly that it feels like one product. Instead of managing email templates in drag-and-drop builders or JSON files, you write JSX.

Example: build a simple invoice email that updates when your invoice template changes. You own the source code. You version it in Git. You test it like a component (`render()` to HTML, check the output, commit). No "template changed" surprises on production.

// lib/emails/InvoiceEmail.tsx
import { Button, Container, Html, Text } from '@react-email/components';

export const InvoiceEmail = ({ invoiceNumber, total, downloadUrl }: any) => (
  <Html>
    <Container>
      <Text>Invoice #{invoiceNumber}</Text>
      <Text style={{ fontSize: '24px', fontWeight: 'bold' }}>${total}</Text>
      <Button href={downloadUrl}>Download Invoice</Button>
    </Container>
  </Html>
);

// Test it
import { render } from '@react-email/render';

const html = render(InvoiceEmail({ invoiceNumber: '001', total: '1200', downloadUrl: 'https://...' }));
console.log(html); // See the output immediately

SendGrid and Postmark don't have this. You're stuck in their template editors. Resend's React Email means your entire email system lives in your repo, ships with your code, and evolves with your product.

The Catch: When Resend Isn't the Answer

Resend is new (founded 2023). If you need SMS (not email), Resend doesn't do it — Twilio still owns that. If you're running on a legacy system and need SOAP/XML webhooks (extreme edge case), Postmark is more flexible. If you're an enterprise with 10M+ emails/month and need a dedicated IP (so your mail doesn't share IP reputation with others), Postmark and SendGrid offer that; Resend doesn't (yet). For 99% of SaaS, Resend is the right call.

Six FAQs

Does Resend support unsubscribe links?

Yes. Pass `headers: { 'List-Unsubscribe': unsubscribeUrl }` to the send() call. Resend handles the rest. Gmail and Outlook show an unsubscribe button automatically. It's a legal requirement in many jurisdictions (CAN-SPAM in the US, GDPR in EU) — add it from day one.

Can I send attachments?

Yes, but keep them small. Pass `attachments: [{ filename: 'invoice.pdf', content: Buffer.from(...) }]`. Resend has a 25MB limit per email. For large files, send a download link instead of attaching the file — it's cheaper and faster.

What's Resend's uptime SLA?

No published SLA yet (they're still a Series A startup). But they're built on top of AWS SES (Amazon's email service), so reliability is inherited. SendGrid and Postmark both publish 99.9% SLA with credits if they miss it. For mission-critical email, this might matter to you.

How do I test emails locally before sending?

React Email has a preview mode. Run `npx react-email dev` and you get a live preview of your email templates in a browser. Edit the JSX, see the changes immediately. Test sent email bodies before touching production. Never deploy untested emails.

Can I track open rates and clicks?

Resend supports click tracking (add `?resend_click=true` to links, they log clicks). Open tracking is trickier (requires a tracking pixel, which some users block). SendGrid and Postmark have this built in with dashboards. Resend logs it but you have to query the API or webhooks. For most SaaS, you don't need this — focus on delivery, not tracking.

What if my email bounces or fails to send?

Resend returns error codes immediately. Hard bounces (invalid email address) fail on the first send attempt. Soft bounces (mailbox full, server temporarily down) retry automatically for 5 days. Check `result.error` in your function to see what went wrong. Log this to Supabase and alert the user if critical (e.g., order confirmation failed).

The Bottom Line

SendGrid is the incumbent that won by being first, then bloated by adding features nobody asked for. Postmark is the reliable, boring choice — great if you've already made the SendGrid mistake and want to escape. Resend is the default for new projects: simple pricing, React Email templates, clean API, and sub-$1k/month spend even at 5M emails/year. Velocity X ships Resend in every build. If you're wiring transactional email into a SaaS product, start here — set up DKIM, write email components in React, send from a Netlify function or Edge Function, and ship. No signup forms, no marketing dashboards, no surprise bills. Ready to integrate Resend into your next project? Check Aidxn Design SaaS builds for partnership details. For webhook-driven payment flows that trigger email, read about Stripe webhooks and idempotency.

Let us make some quick suggestions?
Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.