Editor’s Note: This post was originally published in May 2019 and has been updated in June 2020.
AWS continues to dominate the cloud technology space, with more than 30% of the web running on AWS services in some form. As the service grew, adding features, availability zones, and more, the complexity of its offerings also grew in lockstep. Recognizing this, we published a blog post in 2019 to help illuminate the fog in infrastructure management and application deployment.
Today, given the rapid pace of the evolution of cloud technology, we wanted to revisit our discussion of AWS EC2, Fargate, and Lambda. In this update, we’ll first review the main points of the original discussion before digging into the changes that have come in the past two years.
Setting the Stage for Comparison
Before we touch on the things that have changed, let’s take a moment to re-set the stage. The comparison between EC2, Fargate, and Lambda is a tale of three different technology categories: Infrastructure-as-a-Service, Containers-as-a-Service, and Functions-as-a-Service (aka serverless development). Each technology has benefits and challenges that need to be taken into consideration when choosing your path. So, let’s review each pattern in turn.
IaaS with EC2
Infrastructure-as-a-service, or IaaS, focuses on making sure that your configured infrastructure is always available. With IaaS, you specify the configuration environment needed for your application, and the IaaS provider ensures that your resources are always available, giving you the greatest possible amount of flexibility. This is both a positive in that you are free to do as you please with the machine and a negative in that you now need to manage all the complexity of a fully available server environment. Furthermore, you need to implement all of your own security and scalability tools, adding additional cost and interactions to your development team’s life cycle.
In AWS, IaaS is offered through Elastic Compute Cloud, or EC2. EC2 lets you provision machines of a certain size, then allows you to work with those machines with a 99.9% availability guarantee. EC2 instances are often dedicated to specific tasks in your application, such as hosting your database or handling application requests. EC2 requires that you maintain everything on the provisioned machine yourself, from application deployment to OS patches.
CaaS with AWS Fargate and ECS/EKS
Containers-as-a-Service, or CaaS, is a pattern that has grown dramatically in recent years. Where IaaS solutions like EC2 require you to manage software at the server level, CaaS solutions let you abstract away the complexity of machine configuration by adopting a uniform machine configuration that is shared among multiple services in your application. This sacrifices the flexibility of EC2’s do-what-you-want virtual machines for configuration files that establish your application’s environment. Although this requires less active maintenance than IaaS approaches, you’re still required to keep your base container images up-to-date.
AWS Fargate is Amazon Web Service’s CaaS solution. Fargate integrates with both the Elastic Container Service (ECS) and the Elastic Kubernetes Service (EKS), giving you the power you need to deploy any scale of containerized application, from single-use utility applications to entire containerized microservice architectures. This approach gives you a healthy balance between ease of development and the complexity of managing environments. AWS Fargate also removes a lot of the security headaches that would be present in a more traditional EC2-based architecture, as each container is run in an isolated environment with its own dedicated set of permissions, reducing the potential for bad actors to wreak havoc in your system.
Serverless with AWS Lambda
With the launch of AWS Lambda in 2014, AWS entered the Function-as-a-Service world as its most significant player, offering serverless compute capability months before Google and Microsoft offered the same. Since its inception as the first serverless offering, every major cloud provider has responded with its own version of a serverless pipeline. Serverless functions reduce the focus on infrastructure significantly–even more drastically than Fargate’s high-level view of system resources. Serverless functions are called in containers that are created and destroyed as needed. They share a standardized format and restrict the ability of developers to modify the machine’s configuration.
This approach focuses on deployable functionality to the exclusion of almost everything else. The containers used are limited in size, with no more than 512 MB of disk space available. Additionally, the codebase size limitation of 50 MB encourages smaller units of functionality, which leads to complexity in gaining a full view of system activity.
As these containers are created and destroyed continually, your functions are each running in isolation most of the time. The mechanism used to recycle containers may also occasionally result in the reuse of another function’s container. So it’s important to not leave any sensitive information on the container since, despite its short life span, you do not have full control over access to the machine.
Finding Your Level of Complexity
Choosing the right infrastructure service is a matter of finding your point of comfort along a number of spectrums. The first is the spectrum of complexity. This is a general-sense metric of the time and effort required to bring an application to production, encompassing both the initial configuration of the resources and the ultimate maintenance activity needed.
On this spectrum, AWS EC2 is by far the most complex solution. In allowing you maximum configurability of your tech stack, EC2 has to push the vast majority of maintenance and security activity back onto the end user. Thus, the flexibility offered by EC2 comes at a cost in complexity of management and ongoing maintenance.
On the other side of the spectrum is AWS Lambda. Lambda largely operates based on trigger events that originate in other systems, whether it is a file upload to S3 or an HTTP request made via API Gateway. This provides maximum ease of development and allows you to create efficient processing pipelines for event-driven payloads very rapidly. This, however, comes at the expense of environment configurability–with AWS Lambda, the only true machine configuration you have access to is the amount of memory dedicated to your function containers.
AWS Fargate offers a middle-of-the-road solution in terms of both ease of development and complexity of management. Fargate builds on top of AWS’ existing container services, ECS and EKS, giving you a central location from which to manage the suite of containerized applications that drive value for your business. It provides greatly eased deployment and configuration management practices when compared to EC2 but does so at the expense of limiting machine flexibility to specific container configurations–which still need to be maintained. Compared to AWS Lambda, however, AWS Fargate offers significantly more flexibility in that you have full access to the configuration of each container.
Complexity growth in these services largely maps to the elements that a user has control over in a given system. This graph highlights the components of each system–EC2 (IaaS), Fargate (CaaS), and Lambda (FaaS)–that are managed by the user while simultaneously highlighting the components that are in turn delegated to the platform provider.
Figure 1: Management scopes for IaaS, CaaS, and FaaS
As you can see, greater flexibility roughly correlates to an increase in the number of resources being managed by the user. The ultimate choice of tool, from a complexity perspective, thus depends upon your team’s comfort with maintaining each of the highlighted areas above.
Finding the Right Level of Financial Commitment
In addition to the complexity angle, choosing the right service between EC2, Fargate, and Lambda requires evaluating comparative cost structures. Our EC2 price for an m4.large instance (2 vCPUs, 8 GiB memory) is still $0.10/hour, and AWS Fargate’s price structure has also not changed significantly, meaning that the comparison between the two services still results in the same conclusion: AWS Fargate tends to be a more cost-efficient option than EC2 if you are willing to give up some configuration capability. You can see the continual-use tradeoffs between the two services in the graph below:
Figure 2: EC2 vs. Fargate price comparison
With AWS Lambda, the pricing structure has also not changed to any significant degree since 2018. In our original look at these services, we concluded that you would be able to manage 16,000 invocations of AWS Lambda, with 30 seconds of runtime for the invocation, before the cost of AWS Lambda began to exceed that of EC2. Similarly, the effect of memory on function invocation capacity continues to result in drastic reductions in invocation counts, as seen below:
Figure 3: EC2 vs. AWS Lambda break-even graph
Given that the above pricing structures have not changed in any significant way since our original article, our conclusions from 2018 still hold: Choosing the right AWS Service, from a provider perspective, is simply a matter of determining the level of operational complexity your team is comfortable with. In addition to your team’s operational ability, you’ll also want to carefully consider usage scenarios: If you can achieve your traffic needs in under 16,000 calls per hour, you can likely save some costs going with AWS Lambda over EC2.
Building on the Basics with Third Parties
One of the most significant areas of growth in cloud computing technology has been the evolution of first- and third-party support tools. AWS, for example, has continued to expand its capabilities over the years, adding tools like AWS SAM and Lambda@Edge to make up for the pitfalls in code management and cost overruns respectively. However, the core problem of observability still requires configuration complexity in the provider that raises the overall cost of maintaining your applications.
First-party monitoring tool sets like AWS CloudWatch and X-Ray offer a great starting point, but they are somewhat limited in the amount of full-platform observability they can provide out of the box. Consider the case of a hybrid application, consisting of a collection of containerized microservices and serverless functions driven by AWS SQS. Each technology has robust logging in and of itself, as will be visible in the dashboards for your application, but tying the disparate technologies together into a comprehensive support-driven view still requires significant effort.
Third-party tools offer various ways around this problem, from general frameworks like distributed tracing to third-party applications that integrate with your AWS environment automatically. At Thundra, for example, we just released a new version of our application library that supports the instrumentation of not only serverless functions but also containers and virtual machines, using our easy-to-use software libraries for Java and other languages.
Making the Right Choice
Unfortunately, from a pure cost perspective, there is still no clear winner. The cost structures, when made comparable, all translate to different price points that ultimately represent your overall comfort with complexity in your application’s technology stack. Continued improvements to the underlying technologies (ECS, EKS, SQS, other Lambda triggers, etc.) have driven continued improvements in ease of use and maintainability. But true observability is still only possible through third-party tools in many real-world application situations.
Choosing the right technology for your application thus is an exercise of determining which application components you need to have the capability to control and configure. Gauge your team’s level of comfort with configuration complexity then use that as a guide to determine the appropriate configuration level, along with the approximate activity levels, for your organization. If you don’t truly need full availability and can demonstrate that your application’s activity will not exceed the cost thresholds mentioned above, you can pick your favorite technology: containers with AWS Fargate or functions with AWS Lambda.
Choosing the right technology basis for your application requires selecting between a number of competing priorities. AWS EC2 still gives you the most flexible configuration and the highest availability guarantee, but it does so at a cost for lower-traffic applications.
AWS Lambda, on the other hand, abstracts away the infrastructure layer entirely, allowing you to focus more on delivering critical functionality that grows with your application.
AWS Fargate, in comparison, strikes a balance between configuration complexity and ease of development through a containerized approach that lets applications standardize.
Coupled with third-party tools like Thundra (the only provider to close the hybrid observability gap), options for developers have never been stronger, and you can rest assured you’ll achieve success no matter which technology you choose.