Serverless computing has taken off in recent years as engineering organizations have shied away from the complexity and cost that comes with managing physical servers and even virtual machines hosted on a cloud like AWS. If you are interested in serverless options on AWS, you should be comparing Lambda and ECS Fargate to figure out what fits your use case best. In this blog post we will compare these two AWS services in the following areas:
- What Is AWS Fargate?
- What Is AWS Lambda?
- Fargate vs. Lambda in Development
- Fargate vs. Lambda pricing
- Monitoring Fargate vs. Lambda
Lambda and Fargate are fundamentally different as serverless solutions and it can be difficult to understand this difference when looking solely at the AWS marketing or documentation pages. First we will go over the basics of each service so we can then compare them.
What Is AWS Fargate?
AWS Fargate is Amazon’s solution to run docker containers without managing any servers for container orchestration. Where things get confusing with Fargate is that Fargate is actually just one way of running containers in Amazon ECS. ECS supports both running containers on EC2 instances and with Fargate, making it difficult to find good information on Fargate and compare it to a solution that is serverless-only.
Fargate relies on docker containers to run your application. Containers run as ECS Tasks (similar to a Pod if you are familiar with Kubernetes), tasks are managed by Services (similar to a Kubernetes Deployment), and services can be set up with an Elastic Load Balancer to receive external traffic over HTTP. When used this way, tasks are persistent -- your containers will continue to run even if no requests are received, even when running on Fargate. Since your containers are always running, there is no warmup time caused by Fargate.
ECS Tasks can also be configured to run on a schedule or as the result of CloudWatch events. This allows you to use ECS Tasks for jobs that do not require a persistent docker container, and is well-suited for Fargate.
What Is AWS Lambda?
AWS Lambda is a service that allows developers to run code in AWS without provisioning or managing any servers. In the simplest use cases, developers can essentially upload their code and specify the amount of memory for a function and it will run when invoked. You can think of Lambda functions as ephemeral - the code is only running when it is invoked, and does not consume resources when it is not needed. Since code is not constantly running, there is some warmup time required for functions that are rarely executed.
Here are some of the sources that can trigger a Lambda Function:
- API Gateway
- S3 Events
- DynamoDB Events
- ELB Target Groups
Since Lambda directly runs code that has been uploaded, developers are limited to the runtimes and versions currently supported by Lambda (as of June 2020):
- Node.js (10, 12)
- Python (2.7, 3.6, 3.7, 3.8)
- Ruby (2.5, 2.7)
- Java (8, 11)
- Go (1.x)
- .NET Core (2.1, 3.1)
You may notice that Docker is not included in the Lambda runtimes. That's because Lambda does not support running docker containers—only functions written in the languages and versions listed above. You can, however, implement a custom runtime to run languages that are not directly supported.
Fargate vs. Lambda in Development
One area that often is overlooked in comparison blog posts like this one is how the technologies work in development. Developing your app efficiently is just as important as running it in production efficiently, and you should always consider how different solutions work a dev environment.
Since Fargate essentially just runs docker containers, you can develop locally using docker and run your docker images in Fargate without worrying about compatibility. Docker compose is a great dev tool for running docker containers locally and has the same features available for ECS tasks for configuring network, resource requirements, and easily managing many docker containers. Developing in docker is already very popular and community support is widely available for almost any imaginable scenario. In this sense Fargate outperforms Lambda since the architecture and development process can be completely independent of Fargate.
In Lambda’s early days, it was very difficult to develop because the runtime restrictions and lack of a clear way to run Lambda functions in dev could easily cause dependency issues between development and production. You had to run dev Lambda functions in an actual AWS account to know for sure how it would perform, which was difficult with teams of developers and required your organization to develop tooling to manage this process. In recent years, many tools have been developed by both AWS and the community to make it much easier to create, deploy, and manage Lambda functions:
- AWS Serverless developer tools
- Step-Through Debugging Lambda Functions Locally
- LocalStack - A fully functional local AWS cloud stack
Even with these tools, developing for Lambda can be challenging for large organizations and will require some effort on the part of your team to standardize which tools are used, and what the process looks like for development, QA, and deployment of Lambda functions.
Fargate vs. Lambda pricing
When it comes to billing, Lambda and Fargate use completely separate billing models that are hard to compare to each other or other options for running your code. Most organizations will have to invest heavily in estimating Lambda and Fargate costs, or just try them both out to see the difference under realistic workloads.
If you have a little bit of historical data, you can use our cost predictor tool to project your AWS costs based on past usage.
Fargate is billed on CPU and memory used per hour. The current pricing is found here. ECS does not allow you to configure Fargate to use arbitrary amounts of CPU and memory, and the amount of memory available depends on the amount of configured CPU. SImilar to Lambda, any unused CPU or memory is essentially wasted money so you will want to try and size your application appropriately.
Since Fargate pricing is not based on number of requests or request length, it can be easier to determine the lower and upper bounds for usage and then get a good idea for the pricing range you will be in. You can simply count the number of containers you are using, match them to available Fargate CPU and memory configurations, and calculate the daily cost. You can use the CpuUtilized and MemoryUtilized metrics available with Container Insights to help you size your ECS Tasks in Fargate in production.
For very predictable workloads at higher scales, it may make sense to even use EC2 instances to run some ECS Tasks instead of relying solely on Fargate. You lose the “serverless” aspect of running ECS Tasks but EC2 can be significantly cheaper with spot or reserved instances. Pricing information for EC2 can be found here.
Lambda is billed on a combination of the number of requests, memory, and seconds of function execution. The current pricing is found here. When trying to manage Lambda costs it is important to size your function’s memory requirements properly since it directly affects cost. If you configure your function to use 512Mb of memory but it only consumes 128Mb during execution, you’ve essentially increased the cost of each invocation by 4x. Lambda offers many tiers for memory usage so it should not be too difficult to find a size that closely fits your actual usage.
If you are new to Lambda you should set up CloudWatch Billing Alarms so you can avoid surprises in your bill due to Lambda. You can view your Lambda Function logs to see the memory used and execution time of your lambda invocations to help you properly size your Lambda functions. If your Lambda function is triggered from an event stream such as Kinesis, you can configure your batch size to reduce the number of invocations as well.
Monitoring Fargate vs. Lambda
Monitoring serverless applications can be very challenging. Traditional server monitoring tools do not translate well to Lambda and Fargate, and with fast-paced changes from devs it can be very hard to stay on top of a growing serverless infrastructure.
Fargate exports metrics to CloudWatch automatically. You can check out this blog post which explains how to set up CloudWatch alarms for CPU and Memory utilization for ECS. Similarly to Lambda, most monitoring and logging tools support ECS and therefore Fargate. You can also send logs to CloudWatch and other providers with proper configuration.
Container Insights provides even more visibility into your ECS Tasks with improved logging and metrics. While this feature is only in beta, it looks promising that Amazon is willing to put more effort to increase visibility with ECS.
Important Lambda metrics are exported to CloudWatch automatically. You can check out our How to Monitor AWS Lambda with CloudWatch blog post for details on which metrics are useful and how to create CloudWatch alarms for them, or, if you prefer an automated approach that requires no setup, read How to Monitor AWS Lambda with Blue Matador. In addition to what is available in CloudWatch, there are plenty of monitoring and logging tools that support Lambda such as Blue Matador, SignalFX, SumoLogic, and many more.
One challenge with monitoring Lambda is that there is no underlying server to run monitoring agents on. You may find it necessary to emit application metrics from within your function to meet your monitoring needs, which can incur costs for both execution time and data transfer.
We’ve gone over the basics of what Lambda and Fargate are, how each one works in a development environment, how they are billed differently, and how they can both be monitored easily.
Lambda seems to be the true serverless champion of AWS, and is as close as possible to just running code directly without thinking about any infrastructure. On the other hand, the billing model makes it very difficult to predict costs, and its radically different deployment model can be a challenge for organizations that are used to more traditional deployment models.
Good use cases for Lambda include unpredictable or inconsistent workloads and applications that can be easily expressed as a single function with predictable resource usage on each invocation.
Fargate is clearly more aligned with docker than Lambda, and is likely a good choice for teams that rely heavily on Docker already but do not want to use Kubernetes. With Fargate you also avoid vendor lock-in since you can easily run your docker containers in other services and also other clouds.
Fargate is a good choice for consistent workloads or applications that want to use docker generally.