Transactional email for a one-person app: what you actually need

# email# webdev# node# sideprojects
Transactional email for a one-person app: what you actually needJean Carlos

Disclosure: I build MepMail, an open-source (AGPL-3.0) email API that runs on Amazon SES and accepts...

Disclosure: I build MepMail, an open-source (AGPL-3.0) email API that runs on Amazon SES and accepts Resend's request format. This post is about my own tool. MepMail isn't affiliated with or endorsed by Resend. This post was drafted with AI assistance and reviewed for accuracy.

When you ship a side project on your own, email is easy to underestimate. You need sign-up confirmations, password resets, and maybe a receipt. You don't need a sales call, a contract, or a new SDK to learn. This is the checklist I use, and how MepMail fits each point.

1. A free tier you can stay on for a while

Most solo apps send a handful of emails a day for months. MepMail's Send Free tier gives you 100 emails a day with no card: one domain, one workspace, 1,000 contacts, and 1 MB of attachments per message. The limit is daily (UTC) and there are no overage charges. Up to 50% past the limit, sends keep going; after that they wait in a queue for the next day instead of failing.

Paid Send plans exist for when you grow. Check https://mepmail.dev/pricing for current numbers rather than trusting a blog post.

2. No lock-in to a new SDK

If you already use the official resend package, you can keep it. MepMail accepts the same request shapes for the compatible sending flows, so the change is the key and the base URL:

import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY!, {
  baseUrl: "https://api.mepmail.dev",
});

await resend.emails.send({ from, to, subject, html });
Enter fullscreen mode Exit fullscreen mode

Or set RESEND_BASE_URL=https://api.mepmail.dev in your environment. If your stack only speaks SMTP, there's a relay at smtp.mepmail.dev:2587 with STARTTLS, authenticated with an API key.

To be honest about it, "compatible" doesn't mean "identical". Automated contract tests pin resend@6.27.0 for Node only. Some endpoints (automations, events, logs, oauthGrants) return 404. Inbound over the API and SSO aren't covered. Go and Ruby need a trailing slash on the base URL, while Node, Python, Rust and Elixir must not have one. The Java SDK hard-codes its URL, so use HTTP or SMTP there. The full list is at https://docs.mepmail.dev/sdks.

3. Moving data shouldn't take a weekend

If you're moving an existing account, one command copies contacts, segments, topics, templates, webhooks (signing secrets included), suppressions and domains:

npx @mepmail/cli migrate plan --from resend   # read-only preview
npx @mepmail/cli migrate --from resend
Enter fullscreen mode Exit fullscreen mode

@mepmail/cli is at 0.2.4 on npm. It respects the source's rate limit, keeps keys in memory only (never on disk, no telemetry), can be re-run as a diff, and migrate rollback deletes only what it created. Sent history, API keys and DKIM records stay behind. You publish new DNS records and create new keys.

4. Guardrails you'd otherwise build yourself

A solo dev doesn't have time to babysit reputation. MepMail handles the boring parts:

  • Hard bounces and complaints become suppressions automatically.
  • RFC 8058 one-click unsubscribe headers and a hosted unsubscribe page.
  • Webhooks signed with Standard Webhooks signatures, with a secret you can rotate.
  • Every email gets 21 deliverability checks in the dashboard, from DMARC alignment to List-Unsubscribe.
  • Idempotency via the Idempotency-Key header, so a retried request doesn't send twice.

None of this guarantees inbox placement. Content, your domain's history and the receiving side still matter.

5. Expect some setup time

Plan for lead time before your first real send. Your domain has to pass DNS verification (DKIM and MAIL FROM on SES), and new accounts may go through a security review before they can send at volume. Start this a few days before you need it, not the night before launch.

6. An exit door

The platform is AGPL-3.0. If you'd rather run it yourself, it self-hosts with Docker against your own AWS SES account. You keep SES's own console and pay AWS directly. MepMail Cloud also lets you download the exact source of the version it's running.

What about the bigger providers?

They're good products, and they keep investing. This month, for example, Resend announced Forge, its own mail transfer agent. MepMail isn't trying to out-build anyone at that layer. It runs on Amazon SES. The pitch is narrower: a free daily allowance, an SDK you already know, an open codebase, and a short path in or out.

If you try it and a call your app depends on behaves differently, tell me in the comments. That's the most useful feedback I can get.