Infrastructure2026

Building my own email platform and analytics

A newsletter send engine built on SES within its rate limits, plus an Instagram analytics pipeline that warns me before its own access token expires.

Built forLzCtrl
RoleEngineer
Newsletter Platform
Why build it myself

Email platforms charge by subscriber, so the price climbs at exactly the point the list becomes valuable. I also wanted analytics that answered my questions rather than whichever ones a dashboard had decided to show me.

Sending email properly is harder than it looks. Send too fast and the provider throttles you, and ignore bounces and suppressions and deliverability degrades quietly until very little is landing.

How it works

Subscribers are paginated out of Firestore in pages of 500 and sent in parallel batches deliberately held under the provider rate ceiling, rather than sent as fast as the code can manage.

The analytics pipeline pulls per-post metrics on a schedule, computes the derived numbers I care about, and emails me when its own access token is within two weeks of expiring.

What runs it
  • A send engine with cursor pagination and rate-limited parallel batches
  • Subscribe, unsubscribe, and suppression list reconciliation
  • Per-recipient delivery status tracking
  • A scheduled Instagram Graph API metrics pipeline
  • An analytics dashboard with derived metrics and pace tracking
  • Token expiry alerting
  • A shared email rendering package used by both the composer and the sender
Infrastructure

The parts that took thought

01

Sending slower than the limit allows

Batches are sized and parallelised to sit under the provider ceiling by design, rather than hitting the limit and retrying the failures. A send that respects the ceiling completes; one that does not lands partially and is difficult to reason about afterward.

AWS SESRate limiting
02

Paginated so it does not fall over

Subscribers are cursored in pages rather than loaded at once, so the send behaves the same at a thousand subscribers as at fifty thousand, inside a function execution ceiling that does not move.

FirestoreScale
03

A pipeline that warns me before it breaks

The Instagram integration emails me when its access token is within fourteen days of expiring. Scheduled integrations tend to die on an expired credential and stay dead until someone happens to check, so it tells me first.

MonitoringInstagram API
04

Bounces get dealt with, not buried

Bounces and complaints are reconciled against the provider suppression list rather than left sitting in the subscriber table, because the cost of ignoring them shows up slowly in deliverability.

Deliverability
What I ended up with

I run my own newsletter and my own growth analytics on infrastructure I control, at the cost of the underlying services rather than per subscriber.

It is also the most honest demonstration of the backend work I do, since I am the one who gets woken up when it breaks.

Built with
Backend
TypeScriptFirebase Cloud FunctionsNode
Infrastructure
FirestoreAWS SESesbuild
Services
Instagram Graph API