Choosing Between EC2, ECS, and EKS for Node.js Workloads
Compares how EC2, ECS with Fargate, and EKS handle Node.js apps operationally, helping you pick the right AWS compute service for your team's scale and skills.
This article is published in English.
Sources: EC2 vs ECS vs EKS for Node.js: Which AWS Service Should You Actually Choose?
When it's time to move a Node.js backend onto Amazon Web Services, you run into a decision that has to be made almost immediately. The AWS console presents you with at least three separate compute products: Amazon EC2, Amazon ECS, and Amazon EKS.
Ask around and you'll get contradictory advice. Some developers argue that a plain virtual machine on EC2 is the simplest and best path. Others insist that nothing beats running Kubernetes through EKS if you want a genuinely modern architecture. Meanwhile, many production platform teams have quietly standardized on ECS for their entire fleet of microservices.
Picking the wrong tool tends to push you toward one of two frustrating outcomes: either you end up patching operating systems and babysitting servers by hand, or you find yourself buried in Kubernetes configuration files just to keep a small Express API — one that might only serve a couple dozen requests per second — up and running.
This comparison sets aside the hype and looks directly at how EC2, ECS, and EKS stack up for Node.js applications specifically: what each one asks of your team operationally, and how you can settle on the right option for your situation.
The Three Services Explained Simply
Before comparing trade-offs, it helps to pin down exactly what each service is.
+-------------------------------------------------------------------------+
| Amazon EKS |
| Fully managed Kubernetes. High control, high complexity, multi-cloud. |
+-------------------------------------------------------------------------+
▲
│ Built for complex orchestration
+-------------------------------------------------------------------------+
| Amazon ECS |
| AWS-native container orchestration. Fast, simple, deeply integrated. |
+-------------------------------------------------------------------------+
▲
│ Built for containers
+-------------------------------------------------------------------------+
| Amazon EC2 |
| Raw virtual machines in the cloud. Full OS access, manual maintenance.|
+-------------------------------------------------------------------------+
1. Amazon EC2 (Elastic Compute Cloud)
EC2 hands you a virtual machine, referred to as an "instance." You pick an operating system — Ubuntu and Amazon Linux are common choices — log in over SSH, install Node.js along with a process manager such as PM2, and launch your application yourself.
Everything from the kernel upward is under your direct control.
2. Amazon ECS (Elastic Container Service)
ECS is AWS's own system for orchestrating Docker containers. Rather than administering an operating system directly, you build your Node.js application into a Docker image and instruct ECS to keep a certain number of copies of that container running and healthy — say, four replicas.
If you combine ECS with AWS Fargate, its serverless compute layer, you're freed from managing the servers underneath the containers entirely. AWS allocates CPU and memory for each container automatically, based on demand.
3. Amazon EKS (Elastic Kubernetes Service)
EKS provides managed Kubernetes clusters on top of AWS infrastructure. Kubernetes itself is the open-source container orchestration standard that originated at Google.
With EKS, AWS takes responsibility for the Kubernetes control plane — the master nodes — while you're still on the hook for defining pods, deployments, services, ingress rules, and network policies.
Why Node.js Characteristics Matter Here
Before settling on a service, it's worth recalling a few things about how Node.js actually runs:
- JavaScript execution is single-threaded: a Node.js process only ever uses a single CPU core to run your JS code. Put one process on an 8-core EC2 instance and seven of those cores stay unused unless you explicitly run a cluster of processes or spread work across multiple instances.
- Startup is fast and the footprint is small: a containerized Node.js app can typically be up and running in under two seconds, which makes it well suited to environments built around containers and autoscaling.
- Workloads tend to be I/O-bound: most Node.js services spend the bulk of their time waiting on databases, external API calls, or disk operations rather than performing intensive CPU computation.
These characteristics have a direct bearing on how straightforward — or difficult — scaling turns out to be on each of the three services.
1. Amazon EC2: Maximum Control, Heavy Maintenance
Working with EC2 feels a lot like developing on your own Linux machine, since it essentially is one.
Bash
# Typical manual setup on an EC2 instance:
sudo apt update && sudo apt install -y nodejs npm
git clone https://github.com/your-org/api.git
cd api && npm ci --omit=dev
npm install -g pm2
pm2 start app.js -i max
Traffic ──> Application Load Balancer (ALB)
│
┌────────┴────────┐
▼ ▼
[EC2 Instance] [EC2 Instance]
├─ Node Process ├─ Node Process
├─ Node Process ├─ Node Process
└─ PM2 Manager └─ PM2 Manager
The Pros:
- Predictable pricing: you pay a flat hourly rate tied to whatever instance size you pick.
- Full system access: you can dig into system logs, tune kernel parameters through
sysctl, or install whatever native libraries your application needs.
The Trade-offs:
Running a production workload on EC2 comes with a lot of hands-on maintenance. You're on the hook for:
- Applying operating system security patches.
- Rolling out Node.js runtime upgrades across every instance.
- Maintaining auto-scaling groups and building machine images (AMIs).
- Restarting crashed processes and chasing down memory leaks in long-running services.
Practical Developer Insight: EC2 works well for a single monolithic app that doesn't change much. But once you're running three or four microservices, spreading them across separate EC2 instances either wastes resources or forces you into a cluttered shared server setup.
2. Amazon ECS: The Sweet Spot for Most Teams
If your Node.js app already lives inside a Docker container, ECS tends to be the most efficient path on AWS.
Writing a production-grade Node.js Dockerfile doesn't take much:
# Multi-stage Dockerfile for Node.js
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
Once you push that image to Amazon ECR (Elastic Container Registry), you create an ECS Task Definition that specifies:
- CPU allocation (say,
0.5 vCPU) and memory (say,1 GB) for the container. - Environment variables pulled from AWS Secrets Manager or Parameter Store.
- Health check endpoints.
Traffic ──> ALB
│
├── Path /api/users ──> [ECS Task: Users] (0.5 vCPU)
└── Path /api/orders ─> [ECS Task: Orders] (0.5 vCPU)
[ECS Task: Orders] (0.5 vCPU)
Why ECS with Fargate Shines for Node.js:
Pairing ECS with Fargate removes the server layer entirely — there are no underlying EC2 instances for you to manage.
When traffic spikes, ECS can spin up five new tasks within seconds. Because Node.js processes have a small footprint, you can size compute in thin slices (0.25 vCPU and 512 MB RAM), which keeps idle capacity — and cost — close to zero.
The Trade-offs:
- AWS lock-in: ECS configuration is AWS-specific. A task definition JSON you write for ECS won't transfer to Google Cloud or Azure without rework.
- A thinner tooling ecosystem: ECS plugs neatly into CloudWatch and IAM, but it doesn't have anywhere near the third-party plugin ecosystem that has grown up around Kubernetes.
3. Amazon EKS: Enterprise Scale and Portability
EKS is AWS's managed Kubernetes offering. Kubernetes goes beyond simply running containers — it gives you a common platform for networking, service discovery, rolling deployments, and secret management.
On EKS, your Node.js deployment is described through Kubernetes manifests:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-api
spec:
replicas: 3
selector:
matchLabels:
app: node-api
template:
metadata:
labels:
app: node-api
spec:
containers:
- name: node-api
image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/node-api:v1.2.0
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"
ports:
- containerPort: 3000
The Pros:
- Genuine portability: the same YAML manifests will run on EKS, Google's GKE, Azure's AKS, or on servers in your own data center.
- A broad ecosystem: tools such as Helm, ArgoCD, Prometheus, and Istio integrate through standard configuration.
- Precise autoscaling control: you can scale pods off custom metrics — like the number of messages sitting in an SQS queue or the size of a Redis buffer — using KEDA (Kubernetes Event-driven Autoscaling).
The Trade-offs:
Kubernetes also brings substantial operational weight:
- Control plane cost: EKS bills roughly $73 a month per cluster just to keep the control plane alive, separate from whatever you spend on worker nodes and running containers.
- Steep learning curve: your team needs working knowledge of Ingress controllers, CoreDNS, the Cluster Autoscaler, CNI plugins, and RBAC rules.
A Common Mistake: Teams sometimes reach for EKS purely because Kubernetes is the industry default. For a small engineering team — under 15 developers — keeping a Kubernetes cluster running can eat up 20 to 30 percent of a senior engineer's week, time that could otherwise go toward the product itself.
A Direct Comparison
| Feature | Amazon EC2 | Amazon ECS (Fargate) | Amazon EKS |
|---|---|---|---|
| Abstraction level | Virtual machines | Containers | Containers plus Pods |
| Setup complexity | Low | Low to moderate | High |
| Ongoing maintenance | High (patching, OS, security) | Very low | High (cluster upkeep) |
| Baseline idle cost | Inexpensive (roughly $3-$15/month for a t4g or t3 instance) | You pay only for tasks that are actually running | About $73/month for the control plane, plus compute |
| How fast it scales | Minutes (a full VM has to boot) | Seconds (an image is pulled and a task starts) | Seconds (a pod gets scheduled) |
| Portability across clouds | Low | Low (tied to AWS) | High (standard Kubernetes) |
| Ideal team size | Solo developers or small legacy systems | 2 to 50 engineers | A dedicated platform or DevOps group |
A Practical Way to Decide
Rather than agonizing over every feature, use this straightforward rule of thumb:
Pick EC2 when:
- Your Node.js application is legacy and depends on local background daemons, OS-specific software, or files that must persist on local disk.
- You're spinning up a throwaway prototype on a $5-a-month box where price is the only thing that matters.
Pick ECS with Fargate when:
- You want to run modern, containerized Node.js services without babysitting the underlying operating system.
- Your team is made up of backend engineers without a dedicated infrastructure or DevOps specialist.
- You're fully committed to the AWS ecosystem (DynamoDB, SQS, RDS, IAM) and want security integration that just works out of the box.
- This setup fits roughly 80 percent of companies building on AWS, making it the sensible default.
Pick EKS when:
- You operate dozens or hundreds of microservices spanning multiple languages, such as Node.js, Go, Python, and Java.
- Your organization mandates a multi-cloud or hybrid-cloud approach that needs consistent tooling everywhere.
- You already have a platform or SRE team capable of safely monitoring, securing, and upgrading Kubernetes clusters.
Wrapping Up
Good cloud architecture isn't about picking the flashiest technology available; it's about picking whatever solves the problem with the smallest maintenance tax.
For Node.js specifically:
- EC2 hands you full control but saddles you with routine server upkeep.
- EKS gives you enormous power and the ability to move across ecosystems, at the cost of real complexity and cluster-management overhead.
- ECS with Fargate takes servers off your plate, scales containers within seconds, and frees developers to focus on shipping solid Node.js code.
The sensible path is to start small: wrap your app in a lean Docker container, launch it on ECS first, and only move to Kubernetes later if your organization truly outgrows it. Since the container itself doesn't change, it's already prepared for EKS whenever that day comes.