Alternatives

The SNDR alternative to Mailgun.

A Mailgun alternative engineered for teams that want the same multi-region delivery quality plus first-class observability, idempotency, and a webhook layer built to be replayed.

Mailgun pioneered transactional email infrastructure for developers and has continued to scale through the Sinch acquisition. SNDR's bet is on operational density — a single typed SDK, idempotent send by default, signed webhooks with retries and a replay button, and per-MTA delivery curves visible in the dashboard the moment something starts misbehaving. If you've outgrown Mailgun's UI or want a tighter feedback loop between production and your on-call engineer, this is the page for you.

Side by side

SNDR vs Mailgun

Every row links to where the underlying behavior is documented or implemented.

FeatureSNDRMailgun
REST APISingle /v1 surface, idempotent send/v3 messages API + multiple legacy endpoints
Official SDK@rkiza/sndr — Node 18+, Bun, Deno, Workers, Edgemailgun.js + community ports
Delivery networkMulti-MTA pool with weighted routing + circuit breakersMulti-region IP pools with optional dedicated IPs
Webhook signaturesHMAC-SHA256 over timestamp.body, replay-defendedHMAC-SHA256 with timestamp
Webhook retries12 attempts, exponential backoff with jitter, replay-from-admin8 attempts, fixed retry windows
IdempotencyHeader-driven, SDK auto-generates per callNot first-class for /messages
Per-MTA delivery analyticsBuilt inAggregate per-pool
Inbound emailOn the roadmapYes — mature inbound routes
Email validationStandard syntax + MX check via suppression layerPaid email validation API
Free tier3,000 emails / month, no card requiredNo persistent free tier (paid trial)
Billing currencyUSD via Paddle (MoR)USD direct billing

Drawn from public documentation and pricing as of build time. We try to keep this fair — file an issue if anything is wrong.

Why teams switch

Where SNDR fits better than Mailgun.

Operational observability beats marketing claims

Mailgun’s aggregate dashboards are great for monthly reports. SNDR shows per-MTA, per-recipient-domain delivery curves in real time so an on-call engineer can isolate a misbehaving box in minutes, not days.

Replayable webhooks are not optional

When a customer integration breaks, the most valuable button is "re-fire this exact event with this exact payload." SNDR records every delivery — response code, headers, body — and replays on a single click.

Idempotency on send, by default

The SDK auto-generates an Idempotency-Key per logical send and reuses it across retries. A transient 5xx cannot double-deliver an order receipt. With Mailgun’s /messages endpoint you build this yourself.

Predictable free → paid transition

Mailgun’s post-2021 pricing model removed the persistent free tier. SNDR keeps 3,000 / month free forever, with clean Pro ($12) and Scale ($75) jumps and pro-rated upgrades.

Webhook signature freshness

Every signed payload includes a timestamp; the verifier rejects replays older than 5 minutes by default (tunable). Recovers most of the security posture that token-in-URL or basic-auth approaches lack.

A console that respects your time

Mailgun’s control panel is comprehensive but legacy-dense. SNDR’s admin focuses on the dozen things an operator actually does — replay, suspend with reason, watch MTA pool health, audit-log everything.

Migration

Moving off Mailgun's SDK.

The SNDR SDK uses the same primitives as most modern email clients — install, instantiate with a key, call emails.send. In most codebases the migration is a focused diff.

  1. 1

    Install the SDK

    Add @rkiza/sndr alongside mailgun.js — they coexist while you cut over.

    pnpm add @rkiza/sndr
  2. 2

    Replace the send call

    Mailgun’s messages.create() maps directly. Headers become a typed object; tags become structured key/value pairs for filterable analytics.

    // before
    import formData from 'form-data';
    import Mailgun from 'mailgun.js';
    const mg = new Mailgun(formData).client({ username: 'api', key: process.env.MAILGUN_API_KEY! });
    await mg.messages.create('mg.yourdomain.com', {
      from: 'me@yourdomain.com', to: 'a@b.com', subject: 'hi', html: '<p>hi</p>',
    });
    
    // after
    import { Sndr } from '@rkiza/sndr';
    const sndr = new Sndr(process.env.SNDR_API_KEY!);
    await sndr.emails.send({
      from: 'me@yourdomain.com', to: 'a@b.com', subject: 'hi', html: '<p>hi</p>',
    });
  3. 3

    Migrate webhook handlers

    Mailgun posts form-encoded data; SNDR posts JSON. Verify with the shipped helper and switch your handler to the discriminated-union event shape.

    import { verifyWebhookSignature } from '@rkiza/sndr';
    
    app.post('/webhooks/sndr', express.raw({ type: 'application/json' }), (req, res) => {
      if (!verifyWebhookSignature(req.body, req.header('x-sndr-signature') ?? '', process.env.SNDR_WEBHOOK_SECRET!)) {
        return res.status(400).send('bad signature');
      }
      const event = JSON.parse(req.body.toString('utf8'));
      switch (event.type) {
        case 'email.delivered': /* event.data.email_id, event.data.to */ break;
        case 'email.bounced':   /* event.data.email_id, event.data.error */ break;
        case 'email.unsubscribed': /* event.data.addresses */ break;
      }
      res.status(200).send('ok');
    });
  4. 4

    Reuse your DNS

    SPF can keep both providers’ include: directives during cutover. Add a fresh DKIM CNAME or TXT for the SNDR sending domain — Mailgun’s key stays put.

  5. 5

    Shadow + cut over

    Roll a percentage of sends through SNDR via a feature flag. When per-recipient-domain inbox rate matches Mailgun on the dashboard, flip the rest. Most teams complete the move in under a week.

Want a hand migrating from Mailgun?

We've helped teams move millions of monthly sends across providers without dropping a single delivery. Reach out and we'll walk through your stack.

No shade — Mailgun is a great product. SNDR just optimises for different things.

Start building

Your next message starts here.

Connect your domain, create an API key, and send with SNDR.