How we used AWS to power our backend
Companies are switching to a serverless architecture. It results in a shorter time to market, decreases operational costs and developers can focus on improving applications instead of managing infrastructures.
If you are new to this concept, you might be asking: What is a serverless application? Basically, it’s software that runs in an environment where you don’t need to manage any servers. The host that provides it, is fully responsible for managing all the infrastructure and operational tasks.
One of the solutions that address this, is AWS Lambda. According to a report by Datadog, in less than 5 years AWS Lambda is used by half of the AWS users and is most common in the largest environments.
As a trainee at Imaginary Cloud, I had a project in hands: an application called Dwipper. It consisted of a social network to share shower thoughts (similar to Twitter). I needed to have a backend supporting all the essential operations like authentication and processing data. AWS Lambda could offer all I needed for the backend with the integration of other services AWS offers, such as Cognito, API Gateway, DynamoDB, CloudWatch, CodeCommit and CodePipeline. I even didn’t need to worry about managing servers. But before going straight to the application developed, I want you to understand what AWS Lambda is.
What is AWS Lambda?
AWS Lambda, provided by AWS (Amazon Web Services), is a serverless computing service that allows you to run code with no need to worry about the infrastructure or managing servers. Code executed on AWS Lambda is called Lambda function and once created, it’s ready to run when triggered.
This function can be associated with a specific AWS resource. For example AWS SNS (Simple Notification Service), that is a messaging service. As soon as this resource changes, Lambda executes your function and manages what is needed.
How does AWS Lambda work??
The first thing to do is to create an AWS account. In case you don’t have one, you must configure it. Amazon IAM (Identity and Access Management) provides user management and permissions in AWS. If you’re working as a team, you might need to create an IAM user to give the necessary permissions to your AWS console or in case your application needs to make API calls to AWS.
The next step is to set up your serverless backend, choose what services you will need, configure them and finally, to create your Git repository so you can start working on your application.
Now you can start by writing code in any language supported by AWS Lambda and upload it. You can also write your code in the code editor that Lambda provides. Then you set up your code to be triggered from other AWS services or in-app activity. Lambda receives your request and runs your code only when triggered.
Advantages of using AWS Lambda
AWS Lambda gives you a lot of benefits that you probably should know before choosing any other serverless computing service. If you’ve already asked yourself why to use AWS Lambda, take a look into the main advantages below.
Support multiple languages
For the time being, AWS Lambda does not support all programming languages. But it does support Java, Go, PowerShell, Node.js, C#, Python and Ruby code. For each one of them, AWS provides an SDK that makes it easier for you to write your Lambda functions and integrate them with other AWS services. It also provides a Runtime API, which allows you to use any additional programming languages to author your functions.
In AWS, you pay only for the compute time you consume. You don’t have to pay for the service to host your code. Instead, AWS Lambda bills you based on when that code is executed. You are charged based on the number of requests and the duration, so this excludes the unused minutes of server time.
Fully managed infrastructure
Once your functions are running on AWS infrastructure, it takes care of servers for you. This way, developers have more time to spend improving the product instead of performing operational tasks such as managing the network layer or taking care of scalability.
Let’s imagine that from one moment to another, your application gets loads of new users. This might be a problem if the server is not prepared to handle a massive number of requests. With AWS Lambda you don’t need to worry about it, as the application scales precisely with the size of the workload. It automatically scales your functions according to their demand, so different parts of your application can scale differently according to current usage levels.
Integration with other AWS products
AWS Lambda integrates with AWS services as DynamoDB, API Gateway, Cognito and many more. Each one of those services sends data to your function in JSON as an event that Lambda runtimes convert first into an object, passing it after to your function. All of this allows you to build an application fully functional within your Lambda functions.
When to use AWS Lambda
Like any other computing platform, AWS Lambda is better suited for some scenarios due to its characteristics. First, we will cover in which scenarios it would be a suitable computing service, checking what AWS Lambda used to be, as you can see below:
Imagine that you have an application to upload pictures and resize them to a variety of different sizes. Your application stores those pictures in an Amazon S3 bucket, so probably there’s a Lambda function doing this job of resizing pictures. Amazon S3 is one of the supported AWS event sources that can publish object created events and invoke your Lambda function. All of this is entirely automatic, and there are no servers to manage. Your Lambda function code can read the image object from S3 bucket, create the resize version, and finally save it in another S3 bucket.
Data and analytics
Imagine you are building an application that has data that you need to store. You can use DynamoDB for that, a fully-managed database service, handling write an update and delete items in a table.
Imagine you are building a website and you want to host the backend login on Lambda. Lambda is excellent for this, as the web frontend can send requests to Lambda functions over HTTP endpoints using Amazon API Gateway.
Like websites, Amazon API Gateway can be useful for mobile applications, but it doesn’t end here. You can create, for example, a Lambda function to process clicks within your application.
In addition to these scenarios where this service suits better, it is good to keep in mind the limitations that Lambda carry and realize if it’s actually the best service to integrate into your product.
AWS Lambda limitations
Serverless functions mean you will be dealing with a cold start time. When a function is triggered, there may be a small amount of time waiting between the beginning of the call and when it runs. If this function hasn’t been used in the last 15 minutes this time can be very high, 5 seconds or more.
This can be a potential issue to consider if your workloads are time-sensitive. Some workarounds try to avoid it, for example, keep your functions small and focused, as cold start times increase linearly with memory and code size.
The Lambda functions have some limits such as run time, memory, size and concurrency. The maximum time a function can run is 15 minutes, making Lambda unsuitable for long-running workloads. If your function typically takes more than 15 minutes, AWS Lambda might not be a good solution. The amount of RAM available to the Lambda functions range from 128MB to 3,008MB, in 64MB increments. There is a limit of 75GB as well for all AWS Lambda functions that have been deployed. To avoid this limit, make sure you don’t keep old versions of your Lambda functions. By default, the concurrent execution for all AWS Lambda functions within a single AWS account are limited to 1000. Any Lambda execution triggered above this limit will be forced to wait until other functions finish running. To avoid this, you can request a limit increase by contacting AWS support.
Not always cost-effective
At first glance, the pay only for what you use can produce significant cost savings, but it might not be that way every time. Several factors determine the cost of your Lambda functions and working out this cost is not easy.
If the load for your application increases, this will increase proportionally and might end up being a high cost. You need to have in mind that any other service you decide to use along with your Lambda functions, like API Gateway, CloudWatch or any other, will add to that cost. So you should consider how much you expect your application to scale.
Comparing AWS Lambda with other alternatives
AWS Lambda is not the only serverless service that you can choose for your project. On this topic, you can see other alternatives to Lambda, very similar to it. With a couple of differences you might want to consider when choosing which serverless service to use.
AWS Lambda vs Azure Functions
AWS Lambda and Azure Functions both support Node.js, Python and C# but Azure Functions also support F# and PHP. They also support automatic scaling.
AWS Lambda has a straightforward programming model, while Azure Functions has a more sophisticated one, based on triggers and bindings. The binding system provides extra flexibility, but it also brings some complexity. Both services can run multiple executions of the same function simultaneously.
If you want to add HTTP integration, with AWS Lambda you will have an additional cost, as we already saw, you pay for additional services. On the other hand, Azure Functions come with HTTP endpoint integration and there is no extra cost.
AWS Lambda vs Google Cloud Functions
AWS Lambda and Google Cloud Functions both support Node.js, Python and Go. Lambda allows for unlimited functions, while Google Cloud Functions allows just 1000 functions per project. They also support automatic scaling.
In terms of the maximum execution time of a function, AWS Lambda stays ahead with six more minutes than Google Cloud Functions.
Regarding payment, just like AWS Lambda, with Cloud Functions you pay only for your function’s execution time. You are not billed when your function is idle.
AWS Lambda vs Kubernetes
AWS Lambda and Kubernetes are two different realities. While Lambda is all about going serverless, Kubernetes is all about containers.
On AWS Lambda, you don’t manage the infrastructure and you can’t install any extra software. On Kubernetes, you have to manage the infrastructure and you can install additional software.
Those are just some of the significant and main differences between both of them. In conclusion, if you want to have complete control of the environment, go for a container service like Kubernetes. If you want something more manageable and focus more on improving the product itself, you should choose a serverless service like AWS Lambda.
Other services AWS provides used in our backend
AWS Cognito is a service to manage authentication. You can add user sign-up and sign-in quickly and easily. It still supports sign-in with social identity providers, such as Amazon, Google, and Facebook. It even provides a User Pools feature to help you manage user accounts.
AWS API Gateway
This Amazon service handles all the tasks involved in accepting and processing API calls. It allows developers to define the HTTP endpoints and connect them with the corresponding backend. API Gateway can also validate if the user is authenticated by adding an authorizer to an endpoint mapping connected to a Cognito user pool, meaning that only users in the user pool can access the endpoint.
AWS DynamoDB is a fully managed database that can scale automatically and allows to create database tables that can store and retrieve any amount of data.
Cloudwatch is a service to monitor all your AWS resources, applications and services that run on AWS. It collects data in the form of logs, metrics and events that you can check to quickly solve issues and keep your application running without any trouble.
CodeCommit is a source control service that helps teams collaborate on software development, allowing them to import and host private Git code repositories securely.
AWS CodePipeline is a continuous delivery service that automates the build, test and deploys phases of your release process every time there is a code change based on how you defined the workflow.
How we built a serverless application with AWS
As mentioned before, we integrated some other services with AWS Lambda to build our backend. Our application Dwipper consists of a social network to share thoughts, called Dwipps, where users need to register to start sharing what is on their minds. The functionalities built are:
- recover password/change it
- see all Dwipps from all users
- upvote a Dwipp
- mark a Dwipp as favorite
- create a new Dwipp
- delete and edit a Dwipp
- see the user’s own Dwipps.
We integrated DynamoDB as our database, where we store all the Dwipps created by users from our application, as well as editing and deleting them.
For authentication, AWS Cognito was the solution. It provided an easy management of user authentication that was needed for clients to register their email, generating tokens easily for each user every time they log in to have access to specific content.
To create the REST API and generate the necessary endpoints for all the flow of our application, we integrated Amazon API Gateway. We had to configure AWS Lambda to run our code in response to HTTP requests using API Gateway, which can validate the token generated during login and inject the user data into a lambda environment execution.
Starting with the authentication, we used Cognito User Pools in our function to create a new user account. Regarding the registration, it asks for email and password and the function gets those values, sending them to Cognito and returning the response whether the user has been successfully registered or not. The endpoint is configured in a separate file with the other endpoints, where we put its function. For the login function, we access Cognito once again, sending the user data. In case that user exists, Cognito returns a token needed for the user’s access to the application’s content.
To upvote a Dwipp, we use the same table as before. But for the favorited Dwipps, we had to create a new table. For the first table, we have a function that checks the current user’s email address and if it has already upvoted the Dwipp registered in the table. If yes, the number of upvotes decreases by one and the email address is removed from the list. If not, it increases by one and the email address is added.
As for the function to mark a Dwipp as favorite, we check if that Dwipp is already in the favorite Dwipps’ table. If it’s there, we confirm if that user already favorited it before. If not, a new favorited Dwipp is added to that table. The information of users that favorited a specific Dwipp are kept in the table as well.
With all those available and easy-to-integrating services, we built a working application with authentication and some functionalities in less than one month.
In the beginning, our idea was to use both AWS Lambda and Google Cloud Functions. We’ve decided for AWS as it provides tools for user creation and authentication, while Google Cloud Functions does not. Everything lives up to expectations as all the required functionalities were possible to implement with only AWS.
It may seem like a big deal to understand all those services at first sight, but AWS provides complete documentation clarifying each of them and useful examples. If you take some time to understand it, start trying it out and test it, you will quickly be able to create a full working backend for your application: free of server and infrastructures management, in a short time and with a reduced cost.
Found this article useful? You might like these ones too!
Originally published at https://www.imaginarycloud.com on August 20, 2020.