Skip to main content

May 27th - Blog Subscription Service - Part 1: The Why and the What

· 3 min read
Benjamin Heath
Starfleet Officer(I wish)

I wanted a way for readers to get notified when a new post drops. I looked at the SaaS options Mailchimp, ConvertKit, Buttondown, and they all work fine. But I'd be handing subscriber data to a third party and paying for a service I could build myself. So, I built it. This is the first in a series of posts covering how it works.

The Problem​

The blog runs on Docusaurus, deployed to GitLab Pages. It already generates an RSS feed at /blog/rss.xml. What I needed was something to watch that feed and email subscribers when a new post drops, plus a way for people to sign up and manage their subscription.

The requirements were simple:

  • Subscribers sign up with their email
  • They get a confirmation email and click a link to opt in (double opt-in)
  • When a new post drops, they get an email with a summary and a link
  • They can unsubscribe at any time

No tracking pixels, no analytics, no third-party data sharing.

Why Not a SaaS?​

The honest answer is that it's more interesting to build. But there are more legit reasons too:

  • Cost - at small scale, the AWS services involved are essentially free. SaaS tools charge per subscriber or per send.
  • Content - building it gave me something worth writing about.

The Architecture​

The whole thing runs on AWS, managed with Terraform (I'm pretty new to mermaid so these should improve as time goes on) :

API Gateway (HTTP API) sits at api.mydomain.com and routes three endpoints to a single Lambda: POST /subscribe, GET /confirm, and GET /unsubscribe.

DynamoDB is a single table blog-subscribers with email as the partition key. Each item stores the email, a confirmed flag, and a UUID token used to validate confirmation and unsubscribe requests. A GSI(Global Secondary Index) on the confirmed attribute lets the poller query only confirmed subscribers efficiently.

SES handles all outbound email from a custom domain address. Domain identity, DKIM, and a custom MAIL FROM domain are all configured via Terraform.

EventBridge triggers the poller Lambda on a daily cron. The poller compares the RSS feed against a last_seen timestamp stored in DynamoDB and only sends emails for new posts.

What This Is Not​

This isn't a marketing platform. There's no open tracking, no click tracking, and no segmentation. It's a plain-text (and HTML) email that says "new post dropped, here's the link." That's it.

What's Next​

The next post covers the CI/CD setup. How GitLab authenticates to AWS without storing any credentials and how the permission model is structured to limit blast radius.

This is part of the Blog Subscription Service series.

Ko-fiKeep the coffee flowing