I’ve been a staunch follower of zero-mailbox policy since 2011. Even for my personal mail. Somewhere around 2014, I lost control of my mailbox on Gmail due to the sheer rate at which I started receiving emails. This coincided with Gmail introducing tabs and for a brief period I blamed it on this new feature that might have stolen focus from the inbox into 4 different tabs, but in hindsight Google seems to have been on top of an explosion in email marketing and new service signups that lead to a really busy inbox. And it has gotten really busy. While I received roughly 6 emails/day in 2014, today I receive 30 emails/day.

I switched to Gmail aliases (+ sign). This brought some relief after applying filters to handle the aliases and mark emails as read or directly move them to trash. But this had its own limitations. For a human marketeer spammer seeing my email it was very clear what my actual email address was, the privacy of my email across multiple websites wasn’t really protected and some websites did not allow the + sign at all. I started mulling over hosting my own mail server with a catchall enabled so that I can create new mail address on the fly. But hosting your own mail server had its own perils and the internet was full of warning signs on why not to do this.
However, I had not given up and through the years I had a mental model of what sort of an app I needed. The biggest issue with hosting my own mail server was well-reputed IP addresses for outbound email and highly available servers for inbound email. I needed to use this app only to receive email notifications. With great trust in whatever the serverless fuss is about and an unused domain lying around I started building my own serverless email in 2018.
Building the Email Relay
I wanted to ensure I enjoy building the app while the project stays useful in the long term. I was also customer zero with some interest validated from a few friends. I had to be careful while building this app, as migrating from an email address can be painful so if this app is used by friends n’ family, it should be useful for a long time. I chalked down the following considerations.
- Design the application for reliability: An email can arrive at any time and the sender MTA might not always dial in later.
- Code changes should be shipped with least amount of effort: The fun of the project is to implement features. Ensuring they get shipped quickly accelerates the gratification of seeing a feature work or the despair of seeing it break. Making deployments easy was also going to cut down the pain during overnight bug fixes.
- Spend near-zero time in maintenance: I do not enjoy maintenance neither have committed time for it. ZeroOps is essential.
- Implement measures to prevent data loss: If me or my friends lose an email because the app failed to forward it, it should not be painful to recover the email.
Mail Server
Identifying a service that can help me quickly spin up a mail server capable of sending and receiving emails was crucial. I was familiar with SendGrid and had used it for outbound emails. To receive emails? not really and it seemed like that would need a lot of wiring of webhooks. I wanted to ensure that the service is able to trigger a forwarding logic seamlessly. This pushed me into looking for services with out-of-box integrations. AWS offered just that with Simple Email Service (SES), which could trigger Lambda functions. Perfect fit for building this quickly.
Relay
SES supports emails up to 10MB in size, so it is obvious that SES would only pass along metadata through its Lambda trigger. S3 worked as a good place to dump the complete email for the lambda to refer to and also acted as a backup for processed/unprocessed emails.
User Management
I also wanted to make this work for my friends and family. They should be able to sign-up and login to their individual accounts to manage the email aliases they have generated. The first problem to solve here, was managing user identities. I was certainly not going to build my own identity provider. AWS offered Cognito and it’s integration with Amplify seemed to be the way to go, but for whatever reason I found it more compelx against the comfort I had developed with Firebase. Remember? this had to be fun! So Firebase auth it is and naturally with frontend hosted on Firebase.
I was able to spin up a React based frontend with Cloud Functions to handle alias creation and management in the Firestore.
App Experience
Most of the signups I do are on my mobile device. There were also incidences where I had to write down my email for someone, and using an app to generate email addresses on my phone would be helpful. Building a mobile app is a taxing exercise. Fortunately, Progressive Web Apps exist. I ensured the React build has the right PWA manifest. So my users are able to download the web app and use it like a native app. WIN!

Architecture
With an array of pure serverless components, the email relay has been running gracefully for the last 5 years. The architecture looks like something like this. You might notice Simple Notification Service (SNS) which I haven’t mentioned earlier. SNS helped me split the email forward logic into two lambda functions, ensuring that the function triggered by the SES is able to acknowledge the SES trigger within the required 30 second timeout period. The SNS is used to pass on this event to the next function that does the heavy lifting to sending out an email which can run into intermittent failures.

Reflecting on last five years
When I built this, I optimised for three things: reliability, low maintenance, and fun. Five years in, it’s lived up to that.
The entire service has been costing me less than $2 per month to run for four active users. On average, it processes around 30 emails per day; not trivial traffic, but steady enough to prove it’s useful. There is something deeply satisfying about infrastructure that quietly does its job, month after month, charging your card only for the exact work it performs.
Maintenance has been almost nonexistent. In five years, I’ve spent under eight hours upgrading a deprecated Node.js runtime for one Lambda function. That’s it. No firefighting. No late-night ops panic. No scaling drama. It has largely embodied the ZeroOps principle I had set out to test. For a side project that touches something as sensitive and timing-critical as email, this adventure exceeded my expectations.
The Progressive Web App decision also turned out to be more important than I expected. Because it behaves like a native app, the handful of friends who use it actually formed a habit around it. When an app becomes muscle memory instead of friction, you know you got something right, not in terms of growth metrics, but in terms of the design intent.
Would I open it up to the public? Right now, I’m enjoying the quiet stability of it. Email is deceptively complex; deliverability, abuse vectors, spam compliance, privacy guarantees. The moment you open it broadly, you inherit a different class of responsibility. That’s a different project entirely.
Maybe someday.
For now, I’m content knowing that a small, well-designed serverless system that continues to hum along in the background, solving a very specific problem; reliably, cheaply, and almost invisibly. And sometimes, that’s exactly enough.