Cloudflare email
Build an Email "Server" on Cloudflare (Without a Server at All)
A mail server is six jobs wearing one chassis. Pull them apart and each job turns out to be something Cloudflare already runs for you — no box, no closet, no 2 a.m. pager. This is that machine, taken apart and rebuilt from managed parts.
To see why anyone would bother disassembling it, sit with the old machine on a bad night.
A bad night with the box in the closet
The server hums along for months. Then, quietly, it doesn't.
- 02:14. A reply you sent at bedtime bounces. Buried in the headers: your server's IP address has landed on a blocklist — a neighbor on the same address range got flagged for abuse, and you were painted with the same brush.
- 02:40. You're awake now. Every outbound message is bouncing or sliding straight into spam. Receiving still works, which is the cruel part — nothing looks broken from your side of the screen.
- 03:10. You find the blocklist's delisting form, prove you're not a spammer, and submit it. The reply: allow a day or two for review.
- Morning. You're patching the mail daemon, rotating a key that leaked, and writing an apology to the people whose messages never arrived — none of which is about your email at all.
Nothing about that night was your mail. It was the tax of being your own postmaster: uptime, IP reputation, spam defense, patching, backups. A second job you never applied for, bolted onto the one thing you actually wanted — real addresses on your own domains.
The same machine, taken apart
Here's the move that makes the closet optional. A mail server isn't one indivisible thing; it's a bundle of separate jobs that happen to share a chassis. List them out, and each job maps to a managed Cloudflare service that does exactly that — and nothing else, so there's far less to break.
Email Routing — the receiving half
Email Routing publishes the MX records that tell the world where your domain's mail should go, then catches every message. A catch-all means no address ever bounces. This is the front door, and it's the part that replaces the "listen for incoming mail" job of a classic server.
Workers — the logic
A Worker is code that runs on Cloudflare's network, not on a server. An Email Worker fires the instant a message arrives, so it can decide what to do: which folder, which domain, store it, flag it, or trigger a reply. Workers are the brain that a mail server's rules engine used to be — minus the machine.
R2 — where the messages live
R2 is object storage: a place to keep files, cheaply and at any scale. In a mail setup, each message's body and attachments are stored as a blob in R2. If the app encrypts those blobs before saving them, R2 only ever holds sealed, unreadable data. This replaces the mail server's disk — without the disk.
D1 — the index
D1 is a SQL database. It holds the small, structured facts about each message: who it's from, the subject, the date, which domain and address it came to, whether it's been read, what folder it's in. When you open your inbox, D1 is what makes the list appear instantly, and R2 is what's fetched when you tap a message open.
A reader app — the inbox you actually see
Finally, a web app ties it together into something you'd want to use. Built as a PWA (a web app you install to your home screen or Dock), it reads the list from D1, pulls the sealed message from R2, decrypts it on your device, and shows it like any mail app. Because it's installed, it behaves like a native app, not a browser tab.
A sending API — the outbound half
The one thing Cloudflare's pieces don't do is push mail out to the world. For that, the app calls a transactional email provider's API, with SPF, DKIM and DMARC on the domain so the mail is trusted. That's covered in depth in our guide to sending email with Cloudflare Workers.
The server, mapped — and how heavy each part runs
This is the whole architecture on one page: every job the closet box used to do, the Cloudflare primitive that does it now, and a rough sense of how much weight each part carries. The footprints are deliberately relative — the point is the proportions between them, not any price.
| What a mail server did | Cloudflare primitive | Rough footprint |
|---|---|---|
| Accept incoming mail (MX) | Email Routing | Bursty — fires only when a message arrives, idle the rest of the time |
| Apply rules and filters | Workers | Milliseconds of compute per message; the lightest line in the stack |
| Store message bodies and attachments | R2 (sealed blobs) | The bulk of your storage — attachments dominate, not text |
| Track folders, read/unread, search | D1 | Kilobytes per message; the index is a rounding error beside the bodies |
| Send outgoing mail | Provider API + SPF/DKIM/DMARC | Billed per message by the provider, outside Cloudflare entirely |
| Give you a client to read mail | Installed PWA | Static files served once; effectively free to run |
Read that right-hand column top to bottom and the shape of the whole thing appears. Compute is nearly free, because it only runs the instant mail moves. The index stays tiny — a handful of structured fields per message. The real weight sits in R2, and inside R2 it's attachments, not words, that grow a mailbox: a text-heavy account can run for years inside a footprint you'd measure in gigabytes, not terabytes. Only the sending line lives off Cloudflare, priced by whichever provider you choose.
What the split buys you
Breaking the server into parts isn't just tidy — it's what removes the bad night entirely. There's nothing to keep running, so there's no box to get blocklisted and no daemon to patch at 2 a.m. The bill is a small amount paid straight to Cloudflare for the storage and compute you actually use, with no per-domain tax, so a tenth domain costs the same to add as the first. And because each message body can be sealed before it's written to R2, the platform holds ciphertext, not your mail.
The quieter win is portability. The bodies live in R2 and the index in D1 — both in your account, in standard services, not a vendor's proprietary store. You're never locked inside a walled garden you can be evicted from; your mail is data you hold, in storage you control.
The honest limits
Three caveats, stated plainly. First, mail is briefly in plaintext on arrival. A message exists as readable text for the moment it's received and processed, before it's sealed and stored. Zero-access encryption protects data at rest; it can't make the instant of receipt invisible. Second, sending leans on a provider. Outbound mail goes through a third-party API — you can choose and change it, but you can't avoid it. Third, this isn't a general-purpose mail relay. It's a mailbox for you, not an open server other systems send through. For almost everyone wanting to own their email, those are easy trades.
- Is this really a mail server if there's no server?
- It does everything a mail server does — receive, store, organize, send, and show your mail — using managed services instead of a machine you run. The result is the same ownership with none of the babysitting.
- Where does my mail actually live?
- In your own Cloudflare account: the message bodies in R2 storage, the index in a D1 database. If the app seals the blobs, what's stored is encrypted.
- Can Cloudflare read my mail?
- If messages are encrypted before storage with a key only you hold, the stored data is unreadable to Cloudflare. The honest exception is the brief moment mail arrives in plaintext before it's sealed.
- Do I have to build all of this myself?
- You can, piece by piece — or use an app that already assembles Routing, Workers, R2, D1 and a reader into one inbox you deploy to your own account.