The Problem About Building New Products
The thing about building a product from ground up is basically the development and hosting costs. Being a new product, it will not generate revenue right away. At the same time, we should design a reliable and resilient system so that, if we are up against large amounts of traffic the system should stay responsive. This gives rise to a paradox:
The new product does not generate any revenue yet.
We should rent or buy servers to keep up with any number of requests, so the system remains responsive.
This is why we see a lot of startups are searching desperately for funding and backers.
But this also gives rise to another problem. Even if we rented or bought a bulky server to cope up with a huge traffic. Eventually maybe in a year or two, our traffic can easily outgrow our servers. Then we will need to replace our server or maybe we can buy another server and make changes to our code so it can work with multiple servers.
A Solution: Serverless Architecture
There are different solutions to the problem we just described, maybe one of the most used is setting up Auto Scaling Groups for rented servers (EC2 instances in case of AWS) where a monitoring system like AWS CloudWatch scales up or down the group (i.e., terminates servers or rent new ones continuously depending on CPU or network loads).
While Auto Scaling Groups can be a good candidate for the problem we are facing, we think serverless services like AWS Lambda and Docker shine in this scenario. Auto Scaling Groups can scale up to demand, yes; but after all they are clusters of rented servers and we need to manage these servers (Operating System operations etc.). Auto Scaling Groups make update operations a bit hard on the fly: Think of a scenario where almost all of servers are updated but the update on the last server fails, will you roll back all the updates? Remember you cannot kill every server in your group and update them, since then your app would be offline.
Of course, there are ways to deploy updates without huge rollbacks and offline applications (e.g., Blue-Green deployment) but they are rather cumbersome and a bit slow.
By all means, Auto Scaling Groups are beautiful constructs; but we think they should be used where having a server is required. Setting up development environments, some Big Data applications and of course easily altering legacy applications so they can be scalable.
As we said earlier, we think that serverless services shine in these scenarios. AWS Lambda is a container service for lightweight jobs like sending e-mails, running small SQL queries, etc. It basically means that you write your code and AWS runs it in some computer for you. It is a perfect tool to form the backbone of a web server. We can host the web server on AWS Amplify and every interaction it makes with backend services can be made through AWS Lambda.
However, there are downsides to AWS Lambda too. Two big ones are cold starts and limited compute power.
When a Lambda function is called, AWS wraps up a container for the function to run on. It can take up to one second to deploy the container. It also makes the function warm which means that a second deploy is much faster. This is where the name comes from: if a function is not called for a while, it becomes cold and it takes longer to deploy a container. There are ways to mitigate this effect, perhaps most used is to warm up functions by calling them at times we expect high traffic.
AWS Lambda is a service designed for lightweight jobs. Thus, it has restrictions on size of libraries we can include, size of code, RAM requirements etc.
Meanwhile Docker is designed to do almost everything, so it is a good practice to use Lambda for lightweight background jobs and a Docker Container Service (e.g., AWS ECS) for difficult computations.
Mixit is essentially a multi-objective optimization tool. It takes a list of chemical properties from different products (source products), a target product list as an input. It computes a mixture matrix where the user can see how to mix source products, so he or she can get as close as possible to listed target products. It also can take into account product prices and volumes.
As we discussed above, we are a huge advocate for serverless technologies. Hence, we wanted to use Lambda for our application backend. Maybe it will be easier if we list choices we made on our development journey:
Since the shape operational data is not constant (there are 10 products in one project and 7 in another, same with chemical properties), we wanted to use a No-SQL database for the operational data. AWS DynamoDB was perfect for this job; it stores data as JSON, so no restrictions on shape, it can scale up almost infinitely and it is a managed service, hence no rented servers or whatsoever.
The client data is highly structured, so we used an AWS RDS Postgres server to host our client data.
We deployed a REST API as a frontend-backend communication protocol. Each method of the API is linked to a Lambda function. Those functions handle basic database queries, integrates with AWS Cognito for authorization, basically almost everything.
Only the optimization process is too much for Lambda, it cannot handle it. So we wrapped it up in a Docker image and when an optimization job is requested a Lambda function deploys the image to AWS ECR Fargate (serverless container service of AWS).
Well, try it!
Follow us on Linkedin!