Why we built free programmable email for developers
The path most of us walk is SES, then SendGrid, then Resend — each one fixes the last one's pain, and each one meters the thing a serial shipper does most: another domain, another project, another teammate. So we built MailKite (which we build) to meter only one thing — email volume — with unlimited domains, mailboxes, and teammates, and 3,000 messages a month free. Set it up once, reuse it on every project you launch, pay only when one takes off.
The reason isn’t that the other tools are bad. They’re good — we reached for every one of them before we built ours. The reason is that their pricing is metered on the axis that hurts the way developers work now: you don’t ship one app and scale it, you ship ten market tests a year and hope one lands. Every one wants its own domain, its own sending identity, sometimes its own teammate. Here’s the same pipeline priced two ways — by what you build, or by what you send.
Here’s the punchline in code. One API key, three products on three domains, no plan change between them — because domains aren’t the billed axis:
// one-key.mjs — runs as pasted on Node 18+ (npm install mailkite)
import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY); // one key, every project
// three different products, three domains you own, one free account.
// no "add a domain" upsell, no per-seat plan — the only meter is volume.
await mk.send({ from: "hello@side-project-a.dev", to: user.email, subject: "Welcome", html });
await mk.send({ from: "team@startup-b.io", to: user.email, subject: "Your code", html });
await mk.send({ from: "noreply@weekend-test-c.app", to: user.email, subject: "Ping", html });
The full send-and-receive version — including the inbound webhook, so replies come back to each project — is in the runnable demo repo, demo-programmable-email; open it in StackBlitz and send from three domains in your browser tab. The rest of this post is the honest version of the diagram: where each tool we left genuinely wins, and why the billing axis was the thing we couldn’t fix from the outside.
The walk most of us take: SES, then SendGrid, then Resend
Almost every developer I know arrives at the same three stops, in the same order, for the same reasons.
None of that is a knock. SES really is the cheapest way to push volume. SendGrid really did have to make money. Resend really is a joy to write against. The problem is structural, and it’s the same problem three times: the meter is attached to a count that a developer shipping many small things runs up fast — domains, seats, setup — long before any single project sends enough email to matter.
The way developers actually work now
Ten years ago you built one product and grew it. Now the median indie hacker or small team runs a portfolio: a weekend build, a paid experiment, a client’s MVP, three landing pages testing a wedge. Agentic tooling made this worse (better?) — you can scaffold a deployable app in an afternoon, so people do, constantly. Every one of those needs to send a welcome email, a magic link, a receipt. Every one wants to send from its own domain so the mail isn’t from noreply@some-vendor.com.
On a per-domain or per-seat model, that portfolio is expensive before it earns a cent. On a volume model, it’s free until something works.
What MailKite meters, and what it doesn’t
We picked the one axis that actually costs us money and left everything else alone. Domains, addresses, and teammates are near-zero marginal cost, so they’re unlimited on every plan including Free. Volume is the real cost, so volume is the meter.
| What it costs on MailKite | |
|---|---|
| Domains | Unlimited, every plan. No per-domain fee, ever. |
| Mailboxes / addresses | Unlimited per domain. One inbox per agent, customer, or thread if you want. |
| Teammates | Unlimited. Collaborators on your account aren’t a seat you buy. |
| Inbound + outbound | One shared quota. Received and sent mail count once each, together. |
| The meter | Email volume. 3,000 messages/mo free, then metered per 1,000 — no hard cut. |
The Free plan is 3,000 messages a month across inbound and outbound. That’s roughly a hundred a day — comfortably more than a portfolio of pre-traction projects sends combined, and when one of them crosses the line, you soft-pause with notice, not a surprise bill or a silent ban. Cross it on a paid plan and overage is metered at the plan’s per-1,000 rate; nothing stops mid-send. The pricing page has the exact numbers and the “what we count and why” breakdown.
Where I won’t overclaim
Two honest caveats, because a post with only upsides is an ad. First: at real volume, SES is cheaper per email than we are, and I won’t pretend otherwise — if you’re pushing millions of transactional messages a month and you have AWS muscle in-house, its unit economics are hard to walk away from. Our bet is that most developers shipping most projects are nowhere near that line, and for them the setup tax and the per-region sandbox cost more than the ten cents ever saved. Second: Resend’s developer experience is genuinely excellent, and if you truly only ever run one product on one domain, its free tier fits you and you may never feel the wall. MailKite’s pitch is specifically for the person running many things: the set-it-up-once account you reuse on every launch, where adding the eleventh domain or the second teammate doesn’t change your bill. We built it because we were that person, paying per-domain for a graveyard of experiments.
FAQ
Is MailKite really free for multiple domains? Yes. Every plan, including Free, has unlimited domains with no per-domain fee. The Free plan’s only limit is volume — 3,000 messages a month across inbound and outbound. Spin up a domain per project and you pay nothing until one project’s email volume crosses the line.
How is this different from Resend’s free tier? Resend’s free tier is one domain, 3,000 emails a month, capped at 100 a day; more domains come with paid plans (10 on Pro at $20/mo, 1,000 on Scale at $90/mo). MailKite’s free tier is unlimited domains and unlimited mailboxes with a 3,000 messages/month quota that covers both inbound and outbound, and no daily cap. If you run one product forever, Resend’s tier is fine; the difference shows up on your second and tenth project.
Does MailKite charge per teammate or per seat? No. Collaborators on your account aren’t a billed seat. The only thing metered is email volume. (Hosted webmail mailboxes, when you want a full mailbox with a login and storage, are a separate per-seat add-on — that’s a human with a 10 GB inbox, not a developer with dashboard access.)
What happens when a project takes off and crosses 3,000 messages? On Free, delivery soft-pauses with notice and a one-click upgrade — mail is never lost. On a paid plan, overage is metered at the plan’s per-1,000 rate with no hard cutoff. You pay for the project that grew, not for the ones that didn’t.
Is the free tier permanent, or is this a trial? It’s a plan, not a trial. There’s no 60-day clock and no card required to start. We wrote “unlimited domains, no per-domain fees, ever” on the pricing page precisely because free-tier contractions are the thing that makes developers distrust email vendors, and we didn’t want to be the next one.
If you’re paying per domain for a portfolio of experiments, or you just watched a free tier evaporate, there’s a simpler shape: one account, unlimited domains, metered only when something works. Clone demo-programmable-email (or run it in your browser), then point a domain at MailKite and send from your next three projects on one free key.
Related: email you set up once and reuse for every project, the Amazon SES alternative for developers, and our pricing, and what we count and why.