1
2 Comments

I stopped renting email tools and rolled a real ESP into my SaaS backend. Here's what it actually took.

The stack I kept building for every SaaS I shipped:

Mailchimp or Loops for campaigns: $50 to $99/mo
Postmark or Resend for transactional: $10 to $50/mo
Customer-io or a homegrown drip system for onboarding: $100+/mo or your weekends

Plus glue code to wire billing events into all three, plus a sync job to keep audience lists in sync with your user table, plus a separate merge tag setup in each tool because none of them know your user model.

For a solo founder pre-revenue, that's $15 to $250/mo out the door before you have paying customers. And you still own the integration mess. Every time you add a new billing event, you're updating it in three places.

I got tired of it. So when I started building BuildBase, the React/Next.js SaaS backend SDK I've been shipping with my brother, we decided the email layer wasn't going to be a separate concern. It was going to live inside the same SDK as auth, workspaces, billing, and workflows.

Two years of build later, the last missing piece shipped this week. Wanted to write up what "a real ESP inside your backend" actually means, because I underestimated it badly when we started.

What we thought would take a month

Transactional email is easy. Send a request to an API, get a message ID back, done. If that's all you need, buy Postmark and move on.

Campaign email is where it gets hard. Here's what we ended up needing:

  • Template system with three types: HTML (drag-drop editor via Unlayer), Markdown, and plain text
  • Campaign builder with audience targeting, drafts, scheduling, and bulk send
  • Bring-your-own sender across SMTP, Google, Microsoft, and Mailgun, because the ESP shouldn't dictate your sending reputation
  • Per-template merge tags plus organization-level merge tags for shared values like app name, support email, legal URLs
  • Open tracking via 1x1 pixel, click tracking via link wrapping
  • Unsubscribe groups with preference management (not just a global unsubscribe)
  • Sender account management with DNS verification for SPF/DKIM
  • BullMQ queue with rate limiting (100 per 5 minutes), 5 retries with exponential backoff
  • Background workers for campaign stats, unsubscribe tracking, IP enrichment
  • Full audit trail so you can debug why an email didn't send
  • A dead letter queue for permanently failed sends

That list is the difference between "we send email" and "we run an ESP." Every item on it was a week of work I didn't budget for.

The design lesson I want to share

The last piece shipped this week: organization-level merge tags. Values like {{appName}} or {{supportEmail}} or {{privacyPolicyUrl}} that you set once at the org level and every email template renders automatically.

The interesting decision was around delete behavior. First instinct: let users delete tags. Obvious.

Wrong. If you delete a merge tag that's referenced in a live template, the email renders with a broken placeholder and you don't find out until a customer emails support asking why the subject line says "Welcome to {{undefined}}."

So we made tags immutable. You can archive them, which hides them from the picker and flags them on save if you're editing a template that still references them, but existing templates keep rendering fine. Nothing breaks silently.

Same reasoning applied to the slug. Once a tag is created, the {{key}} is locked forever. Rename requires archive + recreate.

If you're building anything template-driven, steal this pattern. Every variable I've ever nuked in production has come back to bite me. Archive-not-delete costs nothing and prevents an entire class of production incidents.

Was building it worth it?

Honest answer: the ROI hasn't landed yet because BuildBase is still pre first external paying customer. So I can't tell you "we saved $X/mo across N customers."

What I can tell you:

  1. We run four of our own paid products on it (PlugNode, AgentCenter, Imejis, RemoteWait). Every welcome email, password reset, campaign, and drip on those products goes through this system. That's real production traffic. Not scaled, but real.

  2. Merge tags referencing user, workspace, and subscription data don't need a sync job. The template rendering context has direct database access. Every ESP I've paid for required either a batch sync or a real-time webhook to keep audience data current. That's a class of bug that just doesn't exist in this architecture.

  3. One dashboard for the customer. If BuildBase becomes the SaaS backend layer for another founder, they get campaigns, transactional, drips, and audience management in the same place they manage auth and billing. That's the pitch, and it only works because the ESP is native, not bolted on.

What I'd tell anyone at the same fork

If your product only needs transactional email, buy Postmark. It's cheap, deliverable, and someone else handles the deliverability wars with Gmail. Don't build.

If your product needs campaigns + drips + transactional wired to your billing events + audience data that stays in sync with your user table, the integration cost of renting three tools is higher than the sticker price suggests. Build it, or pick a backend that has it built in.

Still missing on my side: bounce webhook handling for hard-bounce suppression, and the RFC 8058 List-Unsubscribe header for Gmail/Yahoo bulk-sender compliance. Both are on the near-term list. I'd rather ship honest than ship overclaimed.

If you want to see it, BuildBase is at https://buildbase.app.

Happy to answer questions on the architecture, the deliverability tradeoffs, or the build-vs-buy math in the comments.

on July 15, 2026
  1. 1

    Two years on the email layer is a serious commitment. What happens to my deliverability when someone else on BuildBase burns the shared IP reputation? That's the bit I'd want answered before ripping out Resend.

    1. 1

      Fair concern but there's no shared ip on our end. for now buildbase isn't an email provider, it's orchestration. you bring your own sender (smtp, google workspace, microsoft, mailgun) so email goes out on your infra with your reputation. nobody else on buildbase can touch it.