← All playbooks
Transactional email migration

Postmark → Resend

Move Postmark sending to Resend by verifying domains, rewriting the API client, and importing each Message Stream’s suppressions. Postmark servers and streams do not exist in Resend. Mustachio templates do not import. Inbound mail needs a new receive path.

Typical timeline8–18 business days24–50 hours active work
Statusneeds review
Source profilePostmark suppressions and getting-started docs reviewed 2026-10-31
Destination profileResend Postmark migration guide and suppressions docs reviewed 2026-10-31
Documentation date
Review window
Evidence4 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

Postmark

Reasons to stay
  • Focused transactional delivery, clear message streams, excellent diagnostics, and support simplify reliable sending
  • Audience, campaigns, automations, and reporting live in one publishing system
Reasons to leave
  • Marketing automation and broad multichannel features are intentionally outside its core scope
  • Automation logic, analytics history, and deliverability settings are not very portable
New platform

Resend

What gets better
  • A simple API, React Email, and clear domain setup make transactional sending approachable for product teams
  • Audience, campaigns, automations, and reporting live in one publishing system
What gets worse
  • Message streams, native template languages, and long IP history from older providers do not transfer in
  • Automation logic, analytics history, and deliverability settings are not very portable
Best of the move

Resend: A simple API, React Email, and clear domain setup make transactional sending approachable for product teams. This removes a major source-side concern: Marketing automation and broad multichannel features are intentionally outside its core scope.

Worst of the move

What you lose: Focused transactional delivery, clear message streams, excellent diagnostics, and support simplify reliable sending. What you inherit: Message streams, native template languages, and long IP history from older providers do not transfer in.

Jump to a section
01At a glance

Know the shape of the move.

Transfer outcome12 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 4, Manual rebuild: 5, Not transferred: 3.
Clean0
Partial4
Manual5
Lost3
Mapping route8 of 9 fields have a destination path

This timeline assumes

  • You send through one or more Postmark Servers and Message Streams, not an inbound-only setup.
  • You can add Resend DNS beside Postmark DKIM and Return-Path records until cutover.
  • Postmark stays able to send until Resend completes one production cycle.
  • The site already documents Postmark → SendGrid and Postmark → Mailgun if Resend is not the destination.
  • You export suppressions from every stream before the first Resend production send.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
Sender signatures and domainsmanualcriticalPostmark needs a confirmed Sender Signature or a verified domain per From address. Resend verifies a domain and then lets you send from any address on it.Verify the Resend domain. Send a test from each production From address.
Servers and Message StreamslostcriticalResend’s Postmark guide says Postmark separates transactional and broadcast traffic on streams. Resend does not have streams. All Resend mail shares one sending path.Split broadcast and transactional traffic with different domains or subdomains if you still need isolation.
API authentication and field namesmanualcriticalPostmark uses X-Postmark-Server-Token and PascalCase fields such as HtmlBody. Resend uses Authorization: Bearer and snake_case fields. To is a comma-separated string in Postmark and an array in Resend.Rewrite the client. Do not send PascalCase JSON to Resend.
TemplatespartialhighPostmark Templates use Mustachio. They do not become Resend templates. Dub’s Resend customer story rebuilt 12 templates in a weekend with React Email. That is a vendor case study, not a template importer.Render HTML in the app or rebuild with React Email.
SuppressionspartialcriticalPostmark suppressions are per Message Stream. The Suppressions tab exports JSON. The API dump is /message-streams/{stream_id}/suppressions/dump. Resend keeps one team-wide list.Export every stream. Merge HardBounce, SpamComplaint, and ManualSuppression rows. Import into Resend before live sends.
WebhooksmanualcriticalResend says it adds sent and delivery-delay events that Postmark does not list, and it keeps webhook request logs. Payload names still change.Map Open, Click, Bounce, Delivery, and SpamComplaint to Resend events. Test one consumer.
Inbound emailmanualhighPostmark’s own Resend migration guide says Postmark inbound webhooks include the full body and attachments. It says Resend inbound webhooks send metadata and need extra API calls for content and attachments. Treat that as Postmark’s description of Resend.Rebuild inbound parsing against Resend’s current receiving docs. Do not assume a drop-in webhook.
SMTPpartialhighResend’s migrate page says both products support SMTP, with different username and port rules. Postmark’s migrate-from-Resend page says Resend is API-only. Follow Resend’s SMTP docs if you still need SMTP.Rehearse SMTP on a staging key. Prefer the API if the SMTP path is unclear.
Dedicated IPs and warm-uplostcriticalStream-scoped IP reputation does not move.Warm the new path. Keep Postmark for leftover volume if inbox placement slips.
Message history retentionlostmediumResend’s migrate page says Postmark keeps 45 days of data and Resend keeps 30.Export any Postmark activity you still need as evidence.
IdempotencymanualmediumResend documents Idempotency-Key on POST /emails and batch. It says Postmark does not currently support idempotency keys.Add keys on the new client so retries do not double-send.
Rate-limit responsespartialmediumResend documents IETF rate-limit headers. It says Postmark errors without those details.Read the new headers. Do not copy Postmark retry code.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
Verified domain or Sender SignatureResend domainmanualVerify DNS, then send from any address on that domain.
Server API tokenResend API keymanualBearer auth. Rotate.
Message StreamDomain, subdomain, or app-level splittransformResend has no stream object.
HtmlBody / TextBody / To stringhtml / text / to arraytransformsnake_case and arrays.
Postmark Template aliasReact Email or rendered htmltransformNo Mustachio import.
Stream suppression dumpResend team suppression listtransformMerge every stream.
Webhook URLResend webhookmanualMap event names.
Inbound streamResend receiving, if still requiredmanualPayload shape changes.
MessageStream parameterNo destinationunsupportedDrop it. Isolate traffic another way.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Keep Postmark tokens, stream suppressions, and DNS so you can send again.

  1. List Servers, streams, From addresses, templates, webhooks, and inbound domains.
  2. Export each stream’s suppressions from the tab or the dump API.
  3. Archive Mustachio templates you still need.
  4. Record DKIM and Return-Path records.
  5. Keep a Postmark token that can still send.

Proof to capture: A manifest lists every stream, suppression file hash, and token owner.

Transformation · Resend SDK or POST https://api.resend.com/emails

API rewrite

Replace the Postmark client with Resend’s send shape.

  1. Switch to Authorization: Bearer.
  2. Map HtmlBody to html and To to an array.
  3. Drop MessageStream.
  4. Add Idempotency-Key on retries.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · Suppressions tab export or /suppressions/dump, then Resend import

Per-stream suppression merge

Build one Resend list from every Postmark stream.

  1. Dump each stream.
  2. Keep EmailAddress, SuppressionReason, Origin, and CreatedAt.
  3. Import the union into Resend.
  4. Test a HardBounce address.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Design

Broadcast and transactional share one Resend path

criticalpossible likelihood

A newsletter blast uses the same domain as password resets.

Consequence
A bad campaign can stain transactional mail.
Mitigation
Use a separate subdomain for broadcasts if you used streams for isolation.

Stop if: A marketing send and a login email share an unapproved domain.

Cutover

One stream’s suppressions never import

criticalpossible likelihood

You exported outbound but skipped a second stream.

Consequence
Resend mails an address Postmark already suppressed.
Mitigation
Check every stream ID against the merge file.

Stop if: A production send hits an address present in any Postmark dump.

Inbound

Inbound parser expects a full Postmark payload

highpossible likelihood

The receiver still reads HtmlBody from the webhook body.

Consequence
Inbound tickets or replies stop.
Mitigation
Pilot the current Resend receive flow. Keep Postmark inbound until it passes.

Stop if: A required inbound message cannot be reconstructed.

06Precise timeline

Do the work in this order.

Estimate forOne Postmark Server with transactional and broadcast streams and app-rendered templates
Total elapsed8–18 business days
Active work24–50 hours
BufferAdd time for inbound rebuild or a large Mustachio conversion.
01
Days 1–3Inventory Postmark2–3 days
02
Days 3–5Dump suppressions2 days
03
Days 5–12Verify and rewrite5–7 days
04
Days 12–16Switch senders1–3 days
05
Days 16–18Watch deliverability3–5 days
  1. Days 1–3 · inventory

    Inventory Postmark

    6–10 hours active2–3 days elapsedOwner review waiting
    • List servers, streams, templates, webhooks, and inbound.
    • Decide how to replace stream isolation.

    Depends on: Postmark and DNS admin access

    Stop / go checkpoint

    Export?

    Go when: Every stream has an owner.

    Stop when: A production stream is unknown.

  2. Days 3–5 · backup

    Dump suppressions

    4–8 hours active2 days elapsedExports waiting
    • Export each stream.
    • Archive templates and DNS.

    Depends on: inventory

    Stop / go checkpoint

    Build Resend?

    Go when: Every stream dump hashes.

    Stop when: A stream is missing.

  3. Days 5–12 · pilot

    Verify and rewrite

    10–22 hours active5–7 days elapsedDNS and inbox tests waiting
    • Verify the Resend domain.
    • Rewrite one send path.
    • Import merged suppressions on staging.
    • Pilot inbound if you use it.

    Depends on: backup

    Stop / go checkpoint

    Cut over?

    Go when: Canary, skip-on-suppression, and inbound pass.

    Stop when: A required template still needs Mustachio.

  4. Days 12–16 · cutover

    Switch senders

    3–8 hours active1–3 days elapsedQueue drain waiting
    • Import production suppressions.
    • Point the app at Resend.
    • Drain Postmark jobs.

    Depends on: pilot

    Stop / go checkpoint

    Resend owns sending?

    Go when: No Postmark production send remains.

    Stop when: A duplicate or a suppressed send appears.

  5. Days 16–18 · observe

    Watch deliverability

    3–6 hours active3–5 days elapsedInbox signals waiting
    • Watch bounces and complaints.
    • Keep Postmark ready.

    Depends on: cutover

    Stop / go checkpoint

    Close rollback?

    Go when: One send cycle is clean.

    Stop when: Rates jump or inbound fails.

07The point of change

Cut over with a way back.

Go live

Cutover

Make Resend the only production sender after every stream’s suppressions are imported.

Recommended window: A low-volume weekday with DNS and app owners on call.

  1. Merge and import the final stream dumps.
  2. Switch the application to the Resend key.
  3. Drain Postmark queues.
  4. Send canaries on transactional and broadcast paths.
  5. Confirm a known HardBounce is skipped.

Proof to capture: Resend sends production mail. Postmark is idle. Known suppressions are skipped.

Return to safety

Rollback

Return sending to Postmark without losing Resend-era suppressions you still need.

Deadline: Before you delete Servers, streams, or tokens.

  1. Stop Resend production sends.
  2. Restore the Postmark token and DNS.
  3. Export new Resend suppressions.
  4. Apply reviewed rows to the matching Postmark streams.
  5. Send a canary through Postmark.

Proof to capture: Postmark is the only production sender again.

Rollback immediately when
  • Suppressed address received mail
  • Duplicate send
  • Inbound parse failure
  • Bounce or complaint spike
  • A From address fails verification
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
V-01BlockingResend domain verifiedSend from each production From address.Resend accepts the message.Domain page and received header.
V-02BlockingEvery stream mergedCompare stream IDs to the import file, then send to a HardBounce address.Every dump is represented. Resend skips the address.Merge sheet and suppression row.
V-03BlockingField namesInspect a canary request.snake_case fields and a to array. No MessageStream.Request log.
V-04BlockingNo Mustachio sendSearch for TemplateAlias in production code.HTML or React Email only.Code search.
V-05BlockingEvent consumerTrigger delivery and bounce on staging.One mapped event each.Consumer log.
V-06BlockingBroadcast domainInspect From domains for newsletters vs transactional mail.Approved split if you used streams for isolation.From audit.
V-07BlockingReceive pathSend a sample inbound message if inbound is in scope.Body and attachments arrive through the new flow.Inbound fixture.
V-08BlockingPostmark still sendsKeep a rollback token and send a staging message.Postmark still accepts mail.Rollback send.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: One full send cycle, stable rates, and seven days without a rollback trigger.

  1. Archive stream dumps and domain screenshots.
  2. Revoke the Postmark production token.
  3. Remove Postmark DNS after mail no longer uses it.
  4. Keep Postmark readable through the retention window.
  5. Document the Resend key rotation.
  6. Schedule the next suppression export review.
10Experiences from the field

When the plan met reality.

First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.

Resend’s Dub customer story says the team moved 12 email templates off Postmark in a weekend and reported no major hiccups. They credit Resend’s docs, React Email, and Tailwind. Dub sends magic links, product alerts, monthly digests, and nurture campaigns. The page is a vendor case study. It does not describe Message Stream isolation, suppression import, or inbound mail.

What they recommend
  • Budget a template rewrite in React Email or HTML. Dub did not import Postmark Mustachio templates.
  • Still export every Postmark stream’s suppressions. This story never says they skipped that step, and it never says they did it.
Worth noticing
  • A weekend template port is the claim Resend published for Dub. It is not a suppression or DNS playbook.
  • React Email is how they replaced Postmark templates in this vendor writeup.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. Resend: migrate from PostmarkAccessed 2026-10-31
  2. Postmark: can I export a list of all bouncesAccessed 2026-10-31
  3. Postmark: Suppressions APIAccessed 2026-10-31
  4. Resend: email suppressionsAccessed 2026-10-31