For almost 2 years, we have been working on an email marketing tool for SMES. It basically allows any user to connect our app to the user’s SES Account. 2 years ago the language and framework decision inside microapps was pretty straightforward: we were strong at Ruby on Rails and PostgreSQL so there was almost no discussion on this.
Almost everything happened within AWS – EC2. Everything, EVERYTHING, was inside that monolithic stone: user authentication, cms, trigger-drip emails, frontend/user interface, plans/pricing-billing management, backend data processing: email composing and so on so forth. While in the middle of the road, we were realizing more and more RoR and the “traditional” MVC approach wasn’t the way to go anymore.
What were the problems?
- Rails had serious performance issues which could have been solved by porting the whole app to Node.js
- The server cost was huge because it had a ‘stone’ that had to be always fully ready to eat web traffic (8080) or to process lots of calculations, even if no user was using our app, the $ counter was ticking every second.
- If the marketing team had to add or edit anything SEO related, like edit or create new landing pages, they were playing within the same core app as developers. Same stays for analytics, user interface, drip emails or changes in plans/pricing – promos/coupons.
- If the developers had to tweak some processes that build the emails or had to fine tune Authentication, they all were hitting the same stone.
- From a developer’s perspective, entering into that ecosystem (lots of models, controllers and views) meant at least 2-3 weeks to start getting the real full picture of the whole huge stone, resulting in costs and eventually less productivity.
Besides the technical part which was a nightmare, the whole app had serious issues due to user onboarding problems. Those were, in fact, because we were forcing users to add their AWS API keys (create a specific IAM user), request for SES production access… That’s how AWS allowed us to go into the SES party by not risking our SES endpoints when it comes to Spammers. So the app was ok, with huge server costs but it was fully functional and it was a good MVP. Thanks RoR!
But, no! users didn’t like the onboarding. And no, managing and doing code changes was a nightmare. Eventually we reached an agreement with AWS people in order to simplify the onboarding to one click and luckily we were going to have the first problem solved! But then again, to fix this problem meant applying core changes to the whole stone. Not sure whether we’d go back to redesign the whole Rails app.
In the meantime we were playing with something called Lambda on tiny Shopify processes and on our digital payments solutions (MONEI). The team was really fast when changing the code, deploying a change/update was possible with click, there were no servers, and the costs incurred only when an action was triggered. Meaning: NO Shopify users hitting that function, NO cost for us. We read some serverless books, got involved with the OS project in order to see if the project had solid roots, and after 2 weeks, our company turned into a fully serverless one. We’d never go back to a monolithic concept when envisioning a long term project with a valid business model.
We have looked into Facebook’s serverless approach: Parse *, but we went to Serverless Framework because it relies on an infrastructure (AWS) we already know, and with a progression, roadmap and background which, today, stays far from Parse. So we had come up with a new approach based on: totally decoupled microservices that generate cost only when they are used, and if they get traction, they are almost infinitely scaleable. Each team member is only responsible for one microservice, and in order to either avoid noise or for security reasons, s/he only has access to his/her microservice.
What does this new infrastructure look like? Here you have a graph of our main project, MoonMail. Credits go to Cloudcraft! Great job!
- CMS: WordPress or preferably Hugo (I’ll dig into this in an upcoming post).
- User’s Frontend: Angular or React within an S3 bucket and assets distributed by Cloudfront.
- Admin’s Frontend: Angular or React within an S3 bucket and assets distributed by Cloudfront.
- Authentication: Auth0 + Cognito
- Multiple Lambda functions grouped by concept that interact between themselves. In fact, a pure and simple Serverless Framework project.
- API Gateway which is the glue or bridge between all Lambda functions when needed.
- Data storage is done using Amazon DynamoDb.
So we now have a big group of tiny microservices, which allows us to work in a reallly distributed way. It’s good because this approach forces us from the beginning to think in the API way, there is NO cost if the project doesn’t get traction, and it even allows us to easily release new features by presenting them to a small group of users to do a kind of A/B testing.
Here is our initial workflow:
- We build the overall infrastructure graph using Cloudcraft. (Here you can see an example).
- We write a doc which broadly explains the overall infrastructure / microservices.
- In the same document, each developer goes into detail and explains exactly how his/her microservice works. In the same document the developer adds each API endpoint of his microservice while defining the actions which can be performed by public or private calls.
- Each developer has access to only his microservice within BitBucket.
- We can still apply TDD and CI.
So yes, serverless and microservices is the future which is here, today. And no, you don’t need to understand Docker anymore!
I want to finish this post by sending a huge thanks to the Serverless Framework community who are doing a great job. We will try to be as open as possible and we will disclose everything from our MoonMail project when it comes to explaining how we organize the microservices and how they interact with each other. So that’s what we learnt from building a monolithic Rails App.
“No server is simpler than no server at all”
*Update. The same day we published this post, Facebook decided to shut down Parse. What an accident.