Resend vs Postmark
Resend and Postmark are both developer-first transactional email APIs, but they grew up in different eras. Postmark has spent over a decade earning a reputation for fast, reliable inbox delivery and strict separation of transactional and broadcast streams, which makes it a favorite for password resets, receipts, and other must-arrive mail. Resend is the newer entrant, built by the team behind React Email, and wins on developer experience: a modern dashboard, first-class React templates, and quick domain setup. In the message model the practical differences show up at the edges — Resend supports scheduled sending natively while Postmark does not, and Postmark exposes structured metadata on each message while Resend leans on tags. Both handle CC, BCC, reply-to, custom headers, and attachments without fuss.
Message field support
Field support as encoded in Email SDK's own adapter capability matrix — the same data the SDK uses to reject sends that would silently drop fields.
| Message field | Resend | Postmark |
|---|---|---|
| CC recipients | ✓ | ✓ |
| BCC recipients | ✓ | ✓ |
| Reply-To address | ✓ | ✓ |
| Custom headers | ✓ | ✓ |
| Attachments | ✓ | ✓ |
| Tags | ✓ | ✓ |
| Metadata | — | ✓ |
| Scheduled sending (sendAt) | ✓ | — |
Fallback compatibility
Failing over from Resend to Postmark loses: scheduled sending (sendat). Email SDK rejects the fallback send for messages that use these fields instead of dropping them silently.
Failing over from Postmark to Resend loses: metadata.
Same code, either provider
With Email SDK the send call is identical for both providers — only the adapter import changes:
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";
const client = createEmailClient({
adapters: [resend({ apiKey: process.env.RESEND_API_KEY! })],
});
await client.send({
from: "hello@yourdomain.com",
to: "user@example.com",
subject: "Welcome!",
html: "<p>It works.</p>",
});Or run both, with automatic fallback:
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";
import { postmark } from "@opencoredev/email-sdk/postmark";
const client = createEmailClient({
adapters: [
resend({ apiKey: process.env.RESEND_API_KEY! }),
postmark({ serverToken: process.env.POSTMARK_SERVER_TOKEN! }),
],
defaultAdapter: "resend",
fallback: ["postmark"],
});FAQ
- Can I switch from Resend to Postmark without rewriting my email code?
- Yes. With Email SDK both providers share one typed send() call and one message shape, so switching from Resend to Postmark is a one-line adapter change plus an API key. The SDK fails fast if a message uses a field Postmark does not support, so nothing is silently dropped.
- Which message fields does Resend support that Postmark doesn't?
- Resend supports scheduled sending (sendat) in the unified message shape, which Postmark does not.
- Can I use Postmark as a fallback for Resend?
- Partially. Email SDK checks field support before every send: a fallback from Resend to Postmark is rejected for messages using scheduled sending (sendat), and from Postmark to Resend for messages using metadata. Messages that avoid those fields fail over cleanly.
Adapter docs
Setup guides: Resend adapter and Postmark adapter. Sending from your own domain? Verify SPF, DKIM, and DMARC with the free email DNS checker.