You have written a service — now you need to run it somewhere so it works around the clock and is reachable from the internet. AWS gives you not one way to do this but four, and each solves the "where do I put my code" problem in its own way. For a newcomer this is confusing: which one to pick and why are there so many?

The good news — the choice follows simple logic. All four options form a ladder from "full manual control" to "I don't think about servers at all". The higher up the ladder, the fewer chores you have, but the more limitations and (sometimes) the higher the price. Let's walk through each rung with clear analogies, and at the end we will give a cheat-sheet table and a breakdown of common mistakes.

EC2 — virtual machines

EC2 (Elastic Compute Cloud) is a virtual computer in the cloud. Imagine you rent an empty desktop tower: it has an operating system, and everything else you install and configure yourself. Install the runtime, apply security updates, bring up your application, restart it if it crashes, add new machines as the load grows — all of that is your job.

In return you get maximum control. You need a specific Linux kernel version, special hardware (a GPU for machine learning), or you are moving an old application "as is" — EC2 gives you that freedom.

The price of freedom is the amount of manual work. Almost nobody advises launching a new service "right on EC2 by hand" today: it is like assembling furniture without instructions when there is a ready-made wardrobe standing next to you. Scaling is set up through Auto Scaling Groups — a mechanism that adds and removes machines by load on its own, but it too needs to be configured.

You can launch a virtual machine from the console in the browser, but in real projects it is done with a command or a description in code. A minimal example via the AWS CLI:

aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type t3.micro \
  --key-name my-key

Here image-id is the operating system image, instance-type is the machine size (how much CPU and memory), key-name is the key for SSH access. Even from this you can see: you will have to think about every such detail.

ECS — containers without Kubernetes

First, about containers. A container is a box that packs your application together with everything it needs to run (runtime, libraries, settings). The box runs identically on a laptop and in the cloud — "it worked on my machine but not on the server" disappears entirely. The most popular format for such boxes is Docker.

ECS (Elastic Container Service) is AWS's own service for running containers. It takes on the manager role: it makes sure the required number of application copies is running, distributes traffic to them, restarts the crashed ones. There are two key concepts here:

  • task definition — the recipe: which container to run, how much memory and CPU to give it;
  • service — the instruction "keep N running copies and balance the load between them".

ECS has two launch modes. You can run containers on your own EC2 machines (in which case the machines themselves are again your job), or on Fargate — a mode where you don't see servers at all: you say "run a container with such-and-such resources", and AWS finds where to place it itself. Fargate greatly simplifies life: there are no machines to patch.

The plus of ECS is simplicity. There are no complex Kubernetes concepts here (no CRDs, Helm, operators), and integration with the rest of AWS works out of the box: access rights via IAM, an ALB load balancer, logs in CloudWatch. The minus is lock-in to a single cloud. ECS knowledge and configs won't move to another cloud, and there are noticeably fewer third-party tools around ECS than around Kubernetes.

EKS — managed Kubernetes

Kubernetes (often written k8s) is an open standard for container orchestration: the same "manager" as ECS, but not tied to AWS and with a huge ecosystem around it. Its complexity is that it needs to be managed — and that is a separate job.

EKS (Elastic Kubernetes Service) takes part of this burden off you: AWS handles the control plane — the brain of the cluster that makes decisions about placing containers. But the nodes (where the containers actually run) remain on you — either as managed node groups (AWS helps update them) or, again, on Fargate.

EKS is chosen when a company already has Kubernetes experience or needs portability between clouds: everything you know about k8s applies here word for word. If you want to dig deeper into Kubernetes itself — start with the fundamentals, deployment and configuration and operations.

An honest caveat: a cluster stays a cluster. Version upgrades, add-ons, setting up permissions via IRSA, network plugins — this work does not go anywhere, there is just less of it. Without a person taking care of it, within a year the cluster accumulates unpatched versions and abandoned components.

Lambda — functions

Lambda is "code with no servers at all". You upload a piece of code (a function), and AWS runs it in response to an event: a file arrived in storage, a message landed in a queue, a scheduled time came. You pay only for the milliseconds while the code was actually running; when idle — almost zero.

This is perfect for glue between services: process an uploaded image, react to a message, run a scheduled task, accept a rare webhook. When there are no events — you pay for nothing.

Lambda and heavy services: where the line runs

Running a full-fledged backend service entirely in Lambda is technically possible, but it is swimming against the current. The main reason is the cold start. When a function hasn't been called for a while, on the next call AWS brings it up from scratch: for a heavy runtime (for example, an environment with a large set of dependencies that boots the whole application context on startup) this takes seconds. For a synchronous API this is a delay the user sees with their own eyes.

There are remedies, but each brings back the very complexity Lambda promised to get rid of:

  • provisioned concurrency — pre-paid "warm" instances that are always ready;
  • minimal runtimes without heavy frameworks;
  • SnapStart — a snapshot of an already warmed-up process that restores in tens of milliseconds (supports Java, Python and .NET).

Then come other limitations. A maximum of 15 minutes per invocation — you can't run a long task that way. The "one request — one instance" model breaks the usual database connection pools: each instance opens its own connection, and the database chokes — you have to add a layer like RDS Proxy. Debugging and running locally are also harder than with containers.

A simple rule: Lambda — for event glue and rare tasks; a constant service with traffic — into a container. The idea "let's rewrite all services as functions" almost always turns out more expensive and slower than it looked in the presentation. More on the serverless approach — in the article on serverless.

Comparison and how to choose

EC2ECS/FargateEKSLambda
ProfileSpecial requirementsConstant services, team without k8sConstant services, has k8s experienceEvents, glue, schedule
Manual workAll on youMinimalNeeds people for the platformAlmost zero
PortabilityHighLow (AWS only)HighLow
Runtime friendlinessFullFullFullWith caveats (cold start)
Price under constant loadLow (with reservations)MediumMediumHigh
Price for rare callsYou pay for idleYou pay for idleYou pay for idleNear zero

A guideline for most teams: have Kubernetes experience — take EKS; don't, and no second cloud is needed — ECS/Fargate; for event-driven code alongside — Lambda selectively. EC2 — only when there is a clear reason you can write down and justify.

Running a service is only the beginning. Next comes the question of how to deliver new versions of the code there without downtime: about that — the articles on pipeline principles and release strategies.

Where this applies

Every team makes this choice when launching its first service in AWS, and it determines all further operation — which is why getting it wrong here is expensive. Here is what most often goes wrong for newcomers:

  • Lambda as a universal architecture. A hundred functions instead of five services turn into a tangled ball: a single user request passes through a dozen functions, each with its own cold start, and tracing the request path is nearly impossible.
  • EKS "because it's trendy". A cluster without a person taking care of it degrades within a year. If there is no dedicated platform team — ECS is more honest and calmer.
  • EC2 with "homemade Docker" in 2026. A do-it-yourself orchestrator made of bash scripts and systemd is the same ECS, only written badly and without support.
  • Forgetting to turn off what you don't need. Fargate and Lambda are more expensive per unit of resources but cheaper when idle; staging and sandboxes that grind away on EC2/EKS at night and on weekends are a direct budget drain. More on that — in the article on cost optimization.

What to study next:

  • AWS fundamentals — how accounts, regions and basic services are organized.
  • IAM — the access rights a service gets in each of the launch options.
  • Scaling and availability — how to survive load growth and failures.
  • Managed data — where the databases and queues the service talks to will live.
  • Integration with the AWS SDK — the code to call AWS services is almost identical in all four options.