July 6, 2026
Split delivery: hosting one mailbox on a different provider

I recently had to solve a problem that sounds trivial and turns out not to be. Here is the setup in plain terms. A company owns a domain, say example.com, and all of its email addresses like hello@example.com are hosted with Google (Google Workspace, the paid business version of Gmail). I wanted just one address on that domain, support@example.com, to live on a completely different email service, Zoho, while every other address stayed exactly where it was on Google. This is called split delivery: same domain, but different addresses handled by different providers.
Sending from support@ through Zoho already worked. Receiving did not. Every test email anyone sent to support@example.com bounced straight back with an error. It took a while to get right, and almost none of the wrong turns were obvious up front. This is the writeup I wish I had found when I started, and I have tried to explain each piece from the ground up rather than assume you already run mail servers for a living.
Why you can’t just point the mailbox somewhere else
The first instinct is to look for a per-mailbox setting: “deliver mail for this one address to that server.” That setting does not exist, because of how mail routing actually works.
Every domain has something called MX records. Think of them as the single street address for an entire apartment building. When someone sends a message to any address at example.com, their mail server looks up that one street address, sees it points to Google, and drops the whole delivery at Google’s door. Google is then the building’s mailroom that sorts messages to individual apartments. The crucial part is that the street address applies to the whole building. There is no way, at this delivery layer, to tell the postal service “everything for this building goes to Google, except mail for apartment support, send that one across town.” The part of an email address before the @ is invisible at the point where delivery is decided. So you cannot split mail by recipient using DNS. It has to be done by whoever runs the mailroom, which here is Google.
So the whole approach is: leave the street address pointing at Google, and configure Google’s mailroom with one instruction. When a message comes in for support@example.com, do not try to deliver it to a local Google mailbox, hand it off to the other provider instead. Everything else keeps working exactly as before.
Do not touch the MX records
This is worth stating on its own because it is the tempting wrong move. If you add the second provider’s MX records alongside Google’s, or switch them over, you break mail for every other address on the domain. The whole point of split delivery is that the MX stays exactly where it is. All the work happens in routing rules, not DNS.
I did find the domain had accumulated some cruft that needed cleaning, but none of it was the MX:
- A second, leftover MX set pointing at the new provider had been added during earlier experimentation. Removed it. MX points only to Google.
- There were two separate SPF records on the domain. SPF is a small DNS entry that lists which servers are allowed to send email using your domain name, so spam filters can tell a real message from a forged one. The rule is that a domain may have exactly one SPF record. Two is not “belt and suspenders,” it is a hard error that makes SPF fail entirely. I merged them into a single record that authorizes both senders (Google and Zoho):
v=spf1 include:_spf.google.com include:zoho.com ~all
- The domain-ownership verification record for the second provider stayed in place. That one is needed and harmless.
Those cleanups mattered for deliverability, but they were not why receiving was broken. That was something else.
The first bounce: the address does not exist
The initial symptom was a bounce, one of those automated “delivery failed” replies (they come from a system politely named the mailer-daemon), saying the address does not exist. That makes sense: support@ is not a real Google mailbox, so when Google receives mail for it, it checks its list of known users, finds nothing, and rejects the message before any routing logic even runs.
The fix for this part is to tell Google that the address is legitimate even though it has no local mailbox, so it stops rejecting it at the door. Once that was in place, a direct check of Google’s inbound server showed it accepting mail for support@ instead of refusing it. Progress. But the mail still was not arriving at the other provider.
The trap that cost me the most time: Routing vs Default routing
Gmail’s admin settings have a section literally called Routing, under Apps, Google Workspace, Gmail. It lets you build rules like “for inbound messages to this recipient, change the route to this other server.” I built exactly that rule. It looked perfect. It did nothing.
The way I finally proved it was doing nothing is the single most useful tool in this entire exercise: Email Log Search (in the admin console under Reporting). It shows you, event by event, what actually happened to a message. For my test email it looked like this:
RECEIVED (SMTP_IN, 250 OK) Google accepted the message
INSERTED queued for LOCAL Gmail delivery
BOUNCED (NoSuchUser) no local mailbox, so it bounced
Notice what is missing: there is no event showing the message being relayed to the other provider. My routing rule never fired. Google received the mail, tried to deliver it to a local Gmail mailbox, found none, and bounced it. The route to the external server was never applied.
Here is why. The rules in the Routing section are evaluated per recipient, after Google has resolved that recipient to a real user. Since support@ resolves to no Google user, the rule is skipped and Google falls straight through to local delivery, which fails.
The correct place for this is a different section entirely: Default routing. Default routing is evaluated at the domain level, before the “this user doesn’t exist” bounce. It is the mechanism specifically designed for routing mail to addresses that have no local mailbox. Same idea, same “change route” action, completely different stage in the pipeline, and that stage is the one that matters here.
Once I rebuilt the identical rule under Default routing instead of Routing, it worked on the first test. The Email Log Search now showed the message being relayed to the external server, and it landed in the destination inbox.
The rule under Default routing is simply:
- Match envelope recipient
support@example.com. - If it matches, modify the message and change its route to the external mail host.
The mail-host definition, and the loop you can create
The “route” a rule points at is a named mail host you define separately (under Gmail, Hosts). This has one setting that will silently break everything if you get it wrong: whether to perform an MX lookup on the host.
Define it as a single host pointing directly at the provider’s inbound server, for example mx.zoho.com on port 25, with MX lookup turned off. If instead you point the host at your own domain, or leave MX lookup on, Google resolves the MX for example.com, which points right back at Google, and you have built a mail loop. The address of the destination server has to be a literal hostname so Google connects to it directly, bypassing the MX record it would otherwise follow.
On the destination provider’s side, the only requirement is that the address actually exists there as a real mailbox and that the domain is set up for hosting mail. The provider will happily accept mail relayed straight to its inbound server regardless of what the public MX says, because Google is connecting to it by name, not via an MX lookup.
Scaling it from one address to a pattern
The version above routes exactly one address. The more interesting case is routing a whole class of addresses. I needed this for a second domain where a batch of addresses that all shared a naming pattern, like alice.team@example.com, bob.team@example.com, and so on, had to live on the other provider while the main mailboxes stayed on Google.
You do not need one rule per address. Default routing’s recipient match accepts a pattern (written as a regular expression, a compact way to describe “any text that looks like this”), so a single rule covers the entire group:
.*\.team@example\.com
That pattern reads as “anything, followed by .team@example.com.” So any address ending in .team@ gets routed to the other provider, and everything else, including the main hello@ mailbox, is left completely alone because it does not fit the shape. Add a new person, create their mailbox on the destination provider, and it just works. You never touch the Google side again.
The one thing to remember with a pattern is that Google will forward every matching address to the other provider, whether or not a mailbox exists there yet. If someone emails a pattern-matching address that has no mailbox on the destination, the destination is the one that bounces it. So create the mailbox before you hand out the address.
What I would tell myself at the start
Most of the time here was spent on things that looked correct. The rule I built was in the wrong section but was otherwise flawless, so nothing about the rule itself pointed at the problem. A few takeaways that would have saved me the detour:
- Mail routing by recipient lives on whoever owns the MX. Do not fight this with DNS.
- For addresses with no local mailbox, use Default routing, not Routing. The distinction is the whole ballgame.
- Email Log Search is the debugger. The
RECEIVED, INSERTED, BOUNCEDsequence with no relay event told me instantly that the rule was not firing, which is what redirected me to the right setting. - Define the destination as a single literal host with MX lookup off, or you will build a loop.
- One SPF record, never two, and leave the MX alone.
Split delivery has a reputation for being fiddly, and it is, but almost all of the fiddliness is in knowing which of two nearly identically named settings does the job. Once the rule is in Default routing and the host is defined correctly, it is boringly reliable, which is exactly what you want from email.