Blog
ReliabilityAdaptersEmail APIs

Email Provider Fallbacks Are a Product Decision

A practical guide to choosing fallback routes for transactional email without silently dropping message fields.

June 5, 20267 min read
Email SDK adapter and fallback routing preview

A fallback route is not a magic second chance. It is a product decision. If the backup provider cannot send the same message, the fallback can turn a provider outage into a quieter bug: the email leaves your app, but the data you meant to send does not.

That is why Email SDK treats adapter limits as part of the API. Providers do not agree on tags, metadata, attachments, headers, reply-to behavior, or batch semantics. A good email layer should admit that instead of smoothing it over.

Start with the email, not the provider

Before picking a backup provider, sort emails by what they need to carry. Password resets and login codes are usually plain. Receipts often need headers, attachments, or metadata. Product notifications sit somewhere in the middle.

Email typeUsually needsFallback posture
Login codePlain text or simple HTMLGood candidate for a broad fallback route.
ReceiptHeaders, metadata, maybe attachmentsUse a provider with equivalent field support.
Product digestTemplate data, tags, unsubscribe behaviorFallback only after checking provider-specific behavior.
Audit or compliance emailStable IDs, metadata, traceabilityBe conservative. Dropped metadata is not harmless.

A small fallback checklist

  • Does the backup adapter support every field this email uses?
  • Will the sender identity work from the same domain?
  • Do you need a different from address, reply-to address, or region?
  • Can your logs tell which provider actually sent the message?
  • Does retrying risk duplicate emails, or is the send idempotent enough?

The boring answer is usually the right one: use fallbacks for simple, time-sensitive transactional email first. Then add stricter routes for messages that carry richer data.

const email = createEmailClient({
  adapters: [
    resend({ apiKey: process.env.RESEND_API_KEY! }),
    postmark({ serverToken: process.env.POSTMARK_SERVER_TOKEN! }),
  ],
  defaultAdapter: "resend",
  fallback: ["postmark"],
  retry: { retries: 1 },
});

Why fail-fast beats silent fallback

Silent fallback feels friendly until something important disappears. If a provider cannot represent metadata, attachments, or custom headers, Email SDK should stop before the request. That failure is annoying, but it is visible. Visible is fixable.

The alternative is worse: a message goes out, dashboards look green, and three weeks later somebody asks why customer receipts stopped carrying the IDs your support team relies on.