Compare providers

SendGrid vs Mailgun

SendGrid and Mailgun are the two heavyweight generalists of email infrastructure, and on the unified message shape they are actually identical: both support every field the SDK models — CC, BCC, reply-to, custom headers, attachments, tags, metadata, and scheduled sending — which makes them fully interchangeable as fallbacks for each other. The decision therefore comes down to the platforms around the API. SendGrid brings Twilio-scale infrastructure, marketing campaigns in the same account, subusers, and granular IP management. Mailgun counters with stronger inbound mail processing, straightforward EU data residency, message retention options, and a reputation for developer-friendly logs and webhooks. Pricing at low volume is comparable; at high volume both reward negotiation, so benchmark real traffic — ideally through the SDK, where swapping the adapter is one line — before committing either way.

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 fieldSendGridMailgun
CC recipients
BCC recipients
Reply-To address
Custom headers
Attachments
Tags
Metadata
Scheduled sending (sendAt)

Fallback compatibility

SendGrid and Mailgun support identical message fields, so Email SDK can fail over between them in either direction without losing data.

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 { sendgrid } from "@opencoredev/email-sdk/sendgrid";

const client = createEmailClient({
  adapters: [sendgrid({ apiKey: process.env.SENDGRID_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 { sendgrid } from "@opencoredev/email-sdk/sendgrid";
import { mailgun } from "@opencoredev/email-sdk/mailgun";

const client = createEmailClient({
  adapters: [
    sendgrid({ apiKey: process.env.SENDGRID_API_KEY! }),
    mailgun({ apiKey: process.env.MAILGUN_API_KEY!, domain: "mg.yourdomain.com" }),
  ],
  defaultAdapter: "sendgrid",
  fallback: ["mailgun"],
});

FAQ

Can I switch from SendGrid to Mailgun without rewriting my email code?
Yes. With Email SDK both providers share one typed send() call and one message shape, so switching from SendGrid to Mailgun is a one-line adapter change plus an API key. The SDK fails fast if a message uses a field Mailgun does not support, so nothing is silently dropped.
Which message fields does SendGrid support that Mailgun doesn't?
Mailgun supports every message field that SendGrid supports, so nothing is lost moving a message from SendGrid to Mailgun.
Can I use Mailgun as a fallback for SendGrid?
Yes — SendGrid and Mailgun support the same message fields, so Email SDK can fail over between them in either direction without dropping data.

Adapter docs

Setup guides: SendGrid adapter and Mailgun adapter. Sending from your own domain? Verify SPF, DKIM, and DMARC with the free email DNS checker.