MoonMail’s engineers mission was to create a “Powered by AWS — SES” SAAS email marketing platform with two only main goals:

Extremely fast performance

Infinite scalability

You know what? We got it! Here’s where we are today:

From the backend perspective we’re fully based on the so popular Serverless Framework, which is fully AWS (so far) by nature. So if the pure sending of emails is handled by SES, who would be the best to handle the architecture than AWS?

MoonMail’s UI needs to be simple, we want it to be simple today and tomorrow, no noise, but I’ll go to the Frontend part a bit later. And I’ll let for a future post the plans on how to keep the Frontend really clean, without holding us back to push really hard to be the best email marketing platform on earth. Yes, we’re ambitious: concepts like AI & Big Data are backlog cards for our engineers, for the next coming months.

Ok, let’s go back to the point. The roots. We used to have an MVP for MoonMail which was fully EC2 — Ruby On Rails. No, no. Costs, performance, scalability…

So we jumped into the Lambda world: Easy, Fast, Fun. But not enough, booom: We Open Sourced MoonMail! Things started getting hot. Really hot. For one week we were one of the 4 top trending projects on GitHub!!! 👏 Even Jeff Barr came to us to say “thanks”! So we have many misions here, today, the “share” what we learnt one.

What does MoonMail’s backend look like?

MoonMail’s backend architecture is fully event driven, does not make use of any traditional servers, and uses Lambda as the only computing service. The project is composed of around 70 Lambda functions, (and counting), written in NodeJS, and are orchestrated by a great set of AWS services, such as:

The web client accesses some of the Lambda functions via API Gateway, which allow our clients to interact with the platform.

Lambda functions needing to communicate with others are connected through SNS.

SQS is used as the queue messaging system in some workflows.

Kinesis Streams capture input streams, like link clicks or email opens that are processed afterwards, for analytical purposes.

MoonMail takes advantage of DynamoDB Streams for data aggregation, for example: bounces and complaint counts.

Whenever one of our users uploads an email list in a CSV file, an S3 event triggers a function to import it into the database.

Periodic tasks, like sending scheduled campaigns are performed by CloudWatch Events.

CloudWatch Alarms allow us to perform certain actions, such as, sending emails when a queue is not empty.

Most of the application data is consistent across several DynamoDB tables. This was chosen as the main data source for two reasons: First, for Infinite scalability and easy integration with Lambda, thanks to Streams. Second, ElastiCache is used for caching purposes and storing non persistent data. Such as, sent email ids that need to be temporarily stored to match bounces/complaint notifications with the email campaign, or the list they correspond with.

What About the Frontend?

MoonMail’s front-end consists of a Single Page Application, built in React and Redux which is hosted in S3 and served through CloudFront, with Route53 as DNS. While also delivering real time notifications via IoT. It obtains temporary AWS credentials for each user with IAM SAML auth provider. This allows them to access the S3 bucket directly through AWS JavaScript SDK for file uploads.

The entire platform is monitored through CloudWatch, including Lambda function logs, and all needed resources are deployed with CloudFormation.

What does MoonMail’s front-end look like?

We’ve also shared MoonMail’s front-end as an Open Source project. This will give you a sneak peek of the technologies we use in production, and also test your deployed MoonMail API.

Angular no, thanks. React. Why did we decide to use React?

For now, React is a very popular and powerful library for building user interfaces. It has more than 50k stars on GitHub. It’s extremely fast and the component based architecture allows a higher level of abstraction. Also, the reusable components are easy to test and maintain.

We use Redux as an application state management library. It gives you a convenient and maintainable way to handle state changes in the application. It is a very small library, easy to test, and it provides you with a great developer experience.

The React + Redux combination, allows MoonMail to quickly scale while keeping the code simple. We envision many features that will require interactivity and provide you with an even better user experience, so we had to find a way to make our “ambitions” “maintainable”.

How do we bundle the MoonMail UI code?

To transpile and minify our JavaScript code, we use Webpack 2 with Babel. It allows us to use the latest ES2015 specifications, which significantly reduces bundle size. Webpack provides out of the box code splitting, allowing the loading parts of this application on demand and tree-shaking, to eliminate dead code.

Where do we host the MoonMail Frontend App to make it available for everyone?

MoonMail Single Page App is hosted in an AWS S3 Bucket. It is available for all users through the CloudFront Content Delivery Network. Cloudfront provides the fastest and most reliable way to gain access to our application. Content is replicated in different regions, which significantly reduces loading times, and also allows us to handle as many requests as needed. Milions per second? No problem. Cloudfront has a menu for each one!

If you like what we’re doing and want to give us a hand, please feel free to contribute on our projects MoonMail and MoonMail-UI on GitHub. If you need help putting MoonMail into production in your AWS account, many Serverless experts around the world will be glad to assist you.