Skip to content

guides

Why you should separate transactional and marketing email

May 22, 2026

#deliverability#sending-domains#transactional-email#marketing-email#dns
Why you should separate transactional and marketing email
Visual: Emergency Emma on okslop

Your password reset email landed in spam. Nothing changed in the reset code. What changed is that last week's newsletter got too many complaints, and the receipts share its domain.

You should separate transactional and marketing email by sending them from different subdomains, each with its own DKIM key and DMARC policy, because mailbox providers score sending reputation per domain and your highest-complaint stream sets the ceiling for everything else. Receipts, password resets, and confirmations have naturally high engagement and near-zero complaints. Newsletters and campaigns have lower engagement and more complaints, no matter how good they are, because some recipients always forget they subscribed. Put both on one domain and the campaign's complaints lower the score that delivers the receipts.

This guide explains the mechanism honestly, then walks the full setup by hand: the subdomains, the SPF and DKIM and DMARC records, and how to verify alignment. At the end I will show how a Cloudflare-native stack treats per-stream domains as the default rather than something you assemble, but the setup below works on any sender.

Should you separate transactional and marketing email?

Yes. Send transactional mail and marketing mail from separate subdomains of the same root domain, each authenticated independently. This is one of the highest-leverage deliverability decisions you can make, and it is invisible until it bites you.

The reason is that reputation is the unit providers actually meter, and the unit of reputation is the sending domain. Gmail, Outlook, and Yahoo each keep a running score for news.example.com that is separate from their score for mail.example.com, derived mostly from how recipients react: opens, replies, "not spam" rescues on the good side; complaints, deletes-without-reading, and spam-trap hits on the bad side. When two streams share a domain, they share that score. There is no way to tell the provider "this message is a receipt, judge it on its own merits." The domain is the verdict.

So the question is not really "are my campaigns good enough to share a domain with my receipts." Even excellent campaigns earn more complaints than receipts do, because marketing mail is, by nature, mail people did not specifically ask for in this moment. The asymmetry is structural, and structural problems want structural fixes. The short list of why the split pays off is in the reasons to split transactional and marketing email, and the split is one of the ways to build and protect your sender reputation overall.

Why does mixing the two streams hurt deliverability?

Mixing them hurts because the two streams have opposite reputation profiles, and a shared domain averages them, dragging the strong stream down to meet the weak one. Here is the asymmetry that makes separation worth the effort:

SignalTransactional mailMarketing mail
Recipient expectationExpected, often awaitedOften forgotten, sometimes unwanted
Open / engagement rateVery high (people open receipts)Lower, varies widely
Complaint rateNear zeroMeaningfully higher
Tolerance for spam-folderingZero (resets must arrive)Painful but survivable
Send patternSteady, event-drivenSpiky, campaign-driven

Look at the last row too. Transactional mail trickles out one message at a time as users act. Marketing mail goes out in bursts of thousands. A sudden volume spike is itself a reputation signal: on a new or lightly-warmed domain it looks like a spam cannon. If that spike shares a domain with your receipts, the throttling providers apply to absorb the burst (deferring mail with temporary 4xx responses) delays your password resets too.

The failure mode is quiet and asymmetric. You will not notice that your newsletter dinged your domain, because the newsletter still mostly arrives. You will notice three weeks later when a user emails support saying the reset link never came, and you cannot reproduce it, because for most recipients it does arrive. By the time you correlate it with the campaign, you have lost trust with the users who needed the receipt most. Separating the streams removes the coupling entirely: a bad campaign can wreck news.example.com without mail.example.com ever noticing.

How do you actually separate them? The manual setup

Separate them by giving each stream its own subdomain, its own DKIM key, and its own DMARC policy. Below is the full setup done by hand, using example.com as the root, mail.example.com for transactional, and news.example.com for marketing.

Step 1: choose the subdomains

Reserve the root example.com for human, person-to-person mail (the address a customer replies to). Put automated streams on subdomains:

  • mail.example.com (or txn.example.com) for transactional: receipts, password resets, confirmations, alerts.
  • news.example.com (or e.example.com) for marketing: newsletters, product announcements, campaigns.

Using subdomains rather than separate root domains matters. Subdomains inherit the brand (@news.example.com is visibly yours) and they can align under the root's DMARC, so you keep one coherent identity instead of scattering reputation across unrelated domains.

Step 2: publish SPF per subdomain

SPF authorizes which servers may send for a domain, and it must be published on the exact subdomain your from address uses, because SPF checks the envelope domain. A record on example.com does not cover news.example.com.

; Transactional stream
mail.example.com.  TXT  "v=spf1 include:_spf.yoursender.example ~all"

; Marketing stream
news.example.com.  TXT  "v=spf1 include:_spf.yoursender.example ~all"

If you forget the subdomain SPF record, here is the failure you will see at the receiver, in the Authentication-Results header of a delivered message:

Authentication-Results: mx.google.com;
  spf=none (google.com: news.example.com does not designate
    permitted sender hosts) smtp.mailfrom=news.example.com;
  dkim=pass header.d=news.example.com;
  dmarc=pass (p=NONE)

spf=none means no SPF record was found for that domain. The fix is to publish the record above on the subdomain, not the root.

Step 3: generate a separate DKIM key per subdomain

This is the step that makes the separation real, and the one people skip. DKIM signs each message with a private key and publishes the matching public key in DNS under a selector. Providers tie reputation to the DKIM d= domain, so each stream needs its own key with d= set to its own subdomain.

; DKIM public key for the transactional stream
s1._domainkey.mail.example.com.  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSq..."

; DKIM public key for the marketing stream (different selector, different key)
s1._domainkey.news.example.com.  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSq..."

If you instead share one DKIM key with d=example.com across both streams, you have undone the whole exercise: providers see one d= domain, score it once, and the streams are coupled again even though the from-addresses differ. Distinct keys on distinct subdomains is the requirement, not distinct from-addresses.

Step 4: set DMARC per subdomain, and lock down the root

DMARC tells receivers what to do when SPF and DKIM fail to align, and it reports who is sending as you. Publish a policy on each sending subdomain, starting permissive so you can read reports before enforcing:

; Per-stream DMARC: start in monitor mode, tighten after reading reports
_dmarc.mail.example.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1"
_dmarc.news.example.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1"

; Root domain: no bulk mail sends from here, so enforce strictly
_dmarc.example.com.  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"

The root gets p=reject because nothing automated sends from the bare example.com, so anything claiming to is spoofing. The subdomains start at p=none (monitor only) and graduate to quarantine then reject once a couple of weeks of aggregate reports show clean alignment. Which of those three policies to use where is the subject of the three DMARC policies explained. Reading those reports is its own skill; the SPF, DKIM, and DMARC setup guide covers the record syntax in depth, the DNS records every sending domain needs is the full checklist each subdomain has to satisfy, and the broader email deliverability guide puts these records in context.

Step 5: send each stream from its own subdomain and verify

Configure your sender so receipts use From: receipts@mail.example.com and campaigns use From: hello@news.example.com. Then verify alignment by reading the Authentication-Results header of a real delivered message in each stream. A correctly separated transactional message looks like this:

Authentication-Results: mx.google.com;
  spf=pass smtp.mailfrom=mail.example.com;
  dkim=pass header.d=mail.example.com;
  dmarc=pass (p=NONE) header.from=mail.example.com

The key line is dkim=pass header.d=mail.example.com. The d= value is the subdomain, not the root, which confirms the streams are signing independently and will be scored independently. Repeat the check on a marketing send and confirm its d= is news.example.com. If both show the same d=, go back to step 3.

Do you need separate IPs as well as separate domains?

Not on Cloudflare-native or HTTPS-API sending, where you do not own a dedicated IP. Domain separation via subdomains and DKIM keys is what carries the reputation split there, because mailbox providers score domain reputation independently of the IP that carried the message. The subdomain split is the higher-leverage move regardless of infrastructure.

On dedicated-IP setups at high volume, separating IPs per stream is also worth doing, since IP reputation is a second axis providers score. But most senders who are getting bitten by this are not on dedicated IPs; they are on a shared or HTTPS-API sender and have simply never split their domains. Cloudflare Workers cannot open outbound port 25 for direct-to-MX SMTP, so edge email goes out over an HTTPS-based sending path where you do not manage IPs at all, which makes the domain split the only lever that matters there, and a sufficient one.

If you also run cold outreach, do not put it on any of these domains. Cold email earns complaints by design, and a single cold campaign can torch a domain's reputation. Keep it on a throwaway domain you are prepared to burn, completely isolated from both your transactional and marketing streams. The specific ways cold tooling damages a legitimate sender are in the cold email habits that wreck your real sending reputation.

When is it fine to skip the separation?

It is reasonably safe to share a domain only when your "marketing" volume is tiny and consists of mail recipients clearly expect, such as a low-frequency product changelog to an opted-in user base with near-zero historical complaints. Below a few hundred genuinely-wanted marketing messages a month, the coupling risk is small.

But that situation is unstable: the day you run your first real campaign, or buy a list, or your changelog grows into a newsletter, the coupling becomes a liability you set up months earlier with no way to retroactively un-mix the reputation. The setup above takes under an hour and costs nothing, and it is far cheaper to do before you need it than to recover a poisoned transactional domain after a bad send. The pricing of mixed-stream failures is covered from the cost angle in what transactional email actually costs; the failure is rarely the bill, it is the resets that silently stop arriving.

Or skip the assembly: per-stream domains as a default

Everything above is mechanical: pick subdomains, publish two SPF records, generate two DKIM keys, set three DMARC policies, point each stream at the right from-address, and read headers to confirm alignment. It is not hard, but it is fiddly, easy to half-finish (the shared-DKIM-key mistake is common), and easy to forget until a campaign reminds you.

Tinbox is a self-contained email stack you deploy onto your own Cloudflare account: D1 for storage, R2 for attachments, Queues for sending, all running on your infrastructure with no per-recipient pricing. Because it is both the transactional sender and the newsletter tool in one deploy, the separation this guide describes is the intended shape rather than a thing you wire together across two vendors. Transactional and marketing are designed to run as distinct sending streams with their own subdomains and DKIM keys, and the deploy walks you through the DNS records each stream needs. You own the domains and the reputation, so the split you build is yours and does not reset when you switch vendors, because there is no vendor to switch.

One honest caveat worth stating plainly: a deploy today is scoped to a single brand and domain (many tenants can live on one Cloudflare account via separate deploys, but multi-domain-per-instance is designed, not yet shipped). The transactional-and-marketing split within that domain is supported and is what this guide is about; running unrelated root domains from one instance is still on the roadmap.

Deploy this yourself: npx tinbox init example.com. The setup walks you through SPF, DKIM, and DMARC for each sending stream so your transactional and marketing reputations start separated. See the docs for per-stream domain configuration and campaign scheduling.

Frequently asked questions

Should I separate transactional and marketing email onto different domains?

Yes, separate them onto different subdomains of the same root domain. Send transactional mail (receipts, password resets, confirmations) from a subdomain like mail.example.com and marketing mail (newsletters, campaigns) from one like news.example.com. Mailbox providers score reputation per sending domain, so mixing a high-complaint newsletter with critical receipts means one bad campaign can send your password resets to spam. Use subdomains rather than entirely separate root domains so both still inherit the brand and DMARC alignment of example.com.

Why does mixing transactional and marketing email hurt deliverability?

Because mailbox providers keep a single reputation score per sending domain, derived mostly from complaint and engagement rates. Marketing mail naturally earns more complaints and lower engagement than transactional mail. When both share a domain, the marketing complaints lower the shared score, and the throttling or spam-foldering that follows hits your receipts and reset emails too. Separating the streams gives each its own score, so the weak stream cannot poison the critical one.

Should transactional and marketing use separate DKIM keys?

Yes. Each subdomain should publish its own DKIM key (its own selector and d= signing domain). This is what makes the reputation separation real: providers tie reputation to the DKIM d= domain, so distinct keys on distinct subdomains produce distinct reputations. Sharing one key across both streams collapses them back into a single reputation even if the from-addresses differ.

Do I need a separate IP for transactional and marketing email?

Not on Cloudflare-native or HTTPS-API sending, where you do not control a dedicated IP. Domain separation via subdomains and DKIM keys is what matters there, because providers score domain reputation independently of IP reputation. On dedicated-IP infrastructure, separating IPs as well is good practice for high volume, but the domain split is the higher-leverage move and the one most senders are missing.

What subdomains should I use for transactional versus marketing email?

A common convention is mail.example.com or txn.example.com for transactional, and news.example.com, e.example.com, or marketing.example.com for marketing. The exact label does not matter to deliverability; what matters is that each is a distinct subdomain with its own DKIM key and DMARC policy. Keep the root example.com reserved for human, person-to-person mail and lock it down with strict DMARC.