Currently there are three major ways for running applications in the cloud.
- Virtual machines such as EC2
- Containers usually running on Kubernetes
- Serverless such as AWS lambda
These three different methods of deploying is a continuum of abstraction. The least abstract of these is virtual machines and the most abstract is serverless. In general you want to move as high up the abstraction continuum as you can.
The right choice for your application will depend on a few factors.
- The amount of state that your application has to store
- What your current environment looks like
- The architecture of your application
All of these will affect how successfully you can move up the abstraction levels. Failure to understand how the more abstract environments work makes things more difficult. This happens by increasing costs and increasing operational complexity.
Virtual machines such as ec2 were historically the way people deployed to the cloud. The patterns for doing this are pretty well known. Much of the configuration for this is done with tools such as Chef and Ansible.
You will see virtual machines used for existing cloud deployments. Many applications currently being built will choose one of the options that is further up the abstraction ladder. When you are dealing with lots of state virtual machines can be easier than using containers or serverless. For example if you need to run a database that is not a managed service for your cloud provider VMs are the right choice.
Some of the reasons that you should use VMs include:
- You have to run stateful applications
- You’ve decided that a lift and shift from the datacenter is the right approach for your application (be very careful here)
- Your service doesn’t horizontally scale well
The reasons why you shouldn’t use VMs:
- Both lift and shift and not being horizontally scalable is usually poor architecture
- The operational burden of using VMs is higher especially when compared to serverless
- Generally less ability to binpack your applications which can increase costs
Generally you should try to be higher up the abstraction ladder then virtual machines. If you have to run your own database or need to move a legacy application to the cloud quickly virtual machines can be the right choice.
Many times applications are already running on VMs and even if they could be moved, the cost benefit ratio might not be there. This is pretty rare and virtual machines are the pattern which should be used the least for greenfield development.
Moving up the abstraction ladder we’ll talk next about containers. This is usually paired with Kubernetes for orchestration however you can use other tools such as ECS. This has advantages when it comes to binpacking, scalability and portability from a developers machine. There are some tradeoffs around this though.
Deploying containers to Kubernetes is becoming one of the more common patterns that you see in large enterprises. Many web applications and larger internal applications are deployed this way. It gives you fine grained control over networking resources while allowing for easy high scalability.
Some of the reasons that you should consider this pattern include:
- Needing horizontal scaling with larger services
- There is a rich open source ecosystem of platform tooling and deployment options
- It’s the most portable of these options and you can move it between cloud providers and on-prem more easily. It’s still not easy, most multicloud stuff is very overhyped.
Some of the disadvantages are:
- Doesn’t run stateful services well
- Operationally it’s intensive there are many moving pieces
- There are lots of choices and there doesn’t yet exist a well agreed upon golden path
Containers provide large amounts of flexibility. They also allow for more efficient deployments and horizontal scaling than you get with EC2 instances. When using Kubernetes you can also get much more powerful deployments such as canaries easily. This all makes running your application in Kubernetes worth considering. If you are going to do this you need to have significant operational experience before you take it on.
Serverless can mean a wide variety of things. In this article I mean using something like AWS Lambda and an API Gateway. This leaves you highly abstracted away from the infrastructure that is running your code. It also comes with lower operational burden because there are few knobs to turn.
This pattern is the least commonly seen in the wild. It can allow for impressive agility and fast deployments when it is working. Serverless does require significant architectural design up front. If you don’t have a well designed microservices architecture things will become messy very quickly.
Some of the reasons you should consider serverless:
- You need to reach a high scale without significant operational burden
- Your code is mostly well defined microservices and you have an event driven architecture
- Smaller units can be deployed lowering blast radius in an incident
Some of the reasons you shouldn’t run serverless:
- Highly stateful services won’t run well in a serverless paradigm
- Cold start can be a problem though there are more options for dealing with this now
- Timeouts will cause problems for long running services
For most modern applications serverless will suit its needs. This pattern is still very underutilized and should be considered more often then it is. The architectural changes that serverless demands are mostly good and more in line with what should be done for a modern application.
How to Choose
All three choices are viable depending on your use case and setup. Like many things in tech, what you should do depends on the circumstances you are in. For most applications I’d start with serverless and then move down the abstraction ladder to find the best choice for you.
There is another large factor which we didn’t cover here which is what already exists within the environment you work in. Understanding what currently exists and what your organization has already built skill in will affect how and what you decide to use.
What the future holds
Ultimately though as technology changes it’s important to keep trying out newer technologies and patterns. Greenfield development efforts are one of the easiest ways to experiment because there is less stuff that can go wrong. This means understanding whether organizational learning is part of the goals of what you’re building.
There are currently emerging possibilities of building with a serviceful architecture. Where we rely completely on managed services. This style isn’t common yet so there isn’t a lot to say about best practices but it’s worth exploring