# AWS ECS on Fargate vs EKS: 7 Evaluation Axes a Startup Should Decide in 3 Months, and an Implementation-Cost Comparison

> The decision-making process for choosing container orchestration, practiced in developing a Minister of Economy, Trade and Industry Award-winning product. For startup CTOs torn over ECS/EKS, I share 7 evaluation axes, concrete cost estimates, and Terraform code examples.

- Published: 2025-01-10
- Author: 友田 陽大
- Tags: AWS, ECS, EKS, Kubernetes, Terraform, インフラ, スタートアップ, 技術選定
- URL: https://tomodahinata.com/en/blog/aws-ecs-vs-eks-startup-decision-framework
- Category: Infrastructure, IaC & CI/CD

## Key points

- For a startup that most prizes learning cost, operational cost, and team-skill dependence, ECS on Fargate is strongly recommended
- Not just infra fees but the labor cost of learning and operating is the true cost, and EKS is about 2x heavier with the control-plane fixed cost + operational effort
- ECS on Fargate is sufficient up to about 10 million monthly PV / ~20 microservices, and below that you can avoid over-investment
- EKS is needed when you have multiple K8s-experienced people, are at the tens-of-millions-PV scale, or absolutely need multi-cloud or an ecosystem like Istio
- ECS → EKS is migratable later, so grow fast on ECS first, watch your scale situation, and you may delay the decision

---

As a startup CTO, or as a Tech Lead designing the initial architecture, have you ever faced the decision "Which should I choose, AWS ECS (Elastic Container Service) or EKS (Elastic Kubernetes Service)?"

In developing a lumber-distribution SaaS that won the Minister of Economy, Trade and Industry Award, I made this decision under the constraint of **a team of 2, with a mandatory release in 3 months**. As a conclusion, I **adopted ECS on Fargate**, and have continued to run it stably to this day.

In this article, I share the **7 evaluation axes** in the ECS vs EKS choice, along with actual cost estimates and Terraform code examples. Not a mere "which is better?" debate, but **a decision-making framework for making the optimal choice within your business constraints**.

---

## Premise: Why This Comparison Matters

### The Reality a Startup Faces

- **Resource constraints**: 1–3 engineers, a budget of ¥100,000–500,000/month
- **Time constraints**: PMF (Product Market Fit) validation mandatory in 3–6 months
- **Technical-debt risk**: an initial-choice mistake could become fatal 2 years later

### Common Failure Patterns

1. **Over-investment from Kubernetes faith**: "EKS, looking ahead to future scale" → development stalls on learning cost
2. **Opportunity loss from underrating ECS**: "EKS is the only choice because Kubernetes is the de facto standard" → overkill for simple requirements
3. **A lack of cost estimation**: "ECS for now" → unexpected billing collapses at scale time

---

## A Quantitative Comparison via 7 Evaluation Axes

The table below is the evaluation framework I actually used. Rate each axis from ★1 to ★5, and **weight it according to your project's priorities**.

| Evaluation axis | ECS on Fargate | EKS | Importance (example) |
|--------|---------------|-----|------------|
| **① Learning cost** | ★★★★★ (low) | ★★☆☆☆ (high) | ★★★★★ |
| **② Operational cost** | ★★★★☆ (low) | ★★☆☆☆ (high) | ★★★★★ |
| **③ Scalability** | ★★★★☆ (sufficient) | ★★★★★ (highest) | ★★★☆☆ |
| **④ Team-skill dependence** | ★★★★☆ (low) | ★★☆☆☆ (high) | ★★★★★ |
| **⑤ Ecosystem** | ★★★☆☆ (AWS-specific) | ★★★★★ (K8s in general) | ★★☆☆☆ |
| **⑥ Vendor lock-in** | ★★☆☆☆ (high) | ★★★★☆ (low) | ★☆☆☆☆ |
| **⑦ Future-proofing / extensibility** | ★★★☆☆ (medium) | ★★★★★ (high) | ★★★☆☆ |

### The Priorities in My Project

**Most important**: ① learning cost, ② operational cost, ④ team-skill dependence
**Reason**: team of 2, 3-month release, no Kubernetes experience

**Result**: ECS on Fargate score **4.2/5.0** vs EKS score **2.8/5.0**

---

## A Detailed Explanation of the Evaluation Axes

### ① Learning Cost: "Can You Operate It in Production in 3 Months?"

**ECS on Fargate**: ★★★★★
- **Learning time**: you can understand task definitions, services, and the cluster concept in 1 week
- **Required knowledge**: only Docker and AWS basics (VPC/IAM/CloudWatch)
- **Few traps**: a simple API, rich documentation

**EKS**: ★★☆☆☆
- **Learning time**: at least 1 month (Pod/Service/Ingress/Deployment/ConfigMap/Secret...)
- **Required knowledge**: Docker + Kubernetes concepts + kubectl + Helm + a deep understanding of networking
- **Many traps**: the complexity of RBAC, network policies, storage classes, etc.

#### Real Experience: The Learning Curve in My Team

```
ECS習得タイムライン:
Day 1-2: Dockerコンテナ化
Day 3-4: Terraformでタスク定義作成
Day 5-7: ALB統合、デプロイ自動化完了

EKS（別プロジェクトで経験）:
Week 1-2: Kubernetes基礎学習（Udemy/公式ドキュメント）
Week 3-4: EKS構築、ネットワーク設定で苦戦
Week 5-6: Ingress/Cert-Manager設定、デバッグ地獄
Week 7-8: ようやく本番投入...
```

---

### ② Operational Cost: "The Reality of Monthly Fees"

#### A Concrete Cost Estimate (10万 PV/month, assuming an API server)

**ECS on Fargate setup**:
```
- Fargate Task (0.5 vCPU, 1GB RAM) x 2台 24時間稼働
  → $35/月
- ALB (Application Load Balancer)
  → $23/月 + データ転送料 $10/月
- CloudWatch Logs (5GB/月)
  → $2.5/月
- RDS (db.t3.small)
  → $30/月
合計: 約 $100/月（約14,000円）
```

**EKS setup**:
```
- EKSコントロールプレーン
  → $73/月（固定費）
- EC2ワーカーノード (t3.medium x 2台)
  → $60/月
- ALB
  → $23/月 + データ転送料 $10/月
- CloudWatch Logs
  → $2.5/月
- RDS (db.t3.small)
  → $30/月
合計: 約 $200/月（約28,000円）
```

**Cost difference**: **about 2x monthly (EKS is higher)**

#### Hidden Cost: Labor

- **ECS**: operations / troubleshooting, 5 hours/month
- **EKS**: operations / troubleshooting, 20 hours/month + learning cost

**Assuming an engineer's unit cost of ¥800,000/month**:
- ECS labor cost: ¥800,000 ÷ 160 hours × 5 hours = **¥25,000/month**
- EKS labor cost: ¥800,000 ÷ 160 hours × 20 hours = **¥100,000/month**

**True cost difference**: ECS ¥165,000/month vs EKS ¥380,000/month = **about 2.3x**

---

### ③ Scalability: "How Far Can You Grow?"

**ECS on Fargate**: ★★★★☆
- **Supportable scale**: sufficient up to about 10 million monthly PV
- **Auto-scaling**: easy with Application Auto Scaling
- **Constraint**: inefficient at extreme scale (thousands of Pods)

**EKS**: ★★★★★
- **Supportable scale**: thousands to tens of thousands of Pods, Google/Netflix class
- **Advanced control**: HPA/VPA/Cluster Autoscaler
- **Flexibility**: custom controllers, Operators

#### Realistic Decision Criteria

**Cases where ECS on Fargate is sufficient**:
- Monthly PV: ~10 million
- Number of microservices: ~20
- Concurrent connections: ~10,000

**Cases where EKS becomes necessary**:
- Monthly PV: 50 million or more
- Number of microservices: 50 or more
- A complex service mesh (Istio, etc.) is mandatory
- A multi-cloud strategy

**My experience**: the Minister of Economy, Trade and Industry Award-winning SaaS was at about 500,000 monthly PV, and ECS had absolutely no problem.

---

### ④ Team-Skill Dependence: "Who Can Maintain It?"

**ECS on Fargate**: ★★★★☆
- **Required skill level**: AWS beginner to intermediate
- **Ease of hiring**: someone with Docker experience can catch up in 1 week
- **Bus-factor risk**: low (rich documentation)

**EKS**: ★★☆☆☆
- **Required skill level**: Kubernetes intermediate or above (CKA-equivalent)
- **Ease of hiring**: K8s-experienced people are scarce in the market and expensive
- **Bus-factor risk**: high (complex config, hard to hand over)

#### The Reality of a Startup

**Scenario**: when a core development member quits

- **ECS**: a new member catches up in 1 week → low risk
- **EKS**: a new member struggles to catch up even in 1 month → high risk

---

### ⑤ Ecosystem: "The Richness of Peripheral Tooling"

**ECS**: ★★★☆☆
- **Strengths**: AWS integration (CloudWatch/X-Ray/Secrets Manager are perfect)
- **Weaknesses**: can't use Kubernetes-standard tools (Helm/Kustomize)

**EKS**: ★★★★★
- **Strengths**: all of the K8s ecosystem (Prometheus/Grafana/ArgoCD/Istio)
- **Weaknesses**: AWS integration needs some manual configuration

---

### ⑥ Vendor Lock-In: "The Future Migration Cost"

**ECS**: ★★☆☆☆ (high lock-in)
- Migrating outside AWS is effectively a full rebuild

**EKS**: ★★★★☆ (low lock-in)
- Migration to GKE/AKS is relatively easy (high YAML compatibility)

#### A Realistic Decision

**Question**: "What's the possibility of migrating off AWS within 5 years?"
- **Low possibility (<10%)**: you can ignore the lock-in risk → ECS is an option
- **High possibility (>30%)**: multi-cloud premise → EKS

In my case, I judged the AWS-migration possibility at 5% or less, and adopted ECS.

---

### ⑦ Future-Proofing / Extensibility: "Can You Keep Using It 2 Years Later?"

**ECS**: ★★★☆☆
- New features keep being added, like AWS Copilot and App Runner
- Evolution toward serverless

**EKS**: ★★★★★
- Kubernetes is the de facto standard
- The continuous evolution of the CNCF ecosystem

---

## Implementation Example: A Comparison in Terraform Code

### ECS on Fargate Setup (Simple)

```hcl
# VPC、セキュリティグループ等は省略

# ECS Cluster
resource "aws_ecs_cluster" "main" {
  name = "my-startup-cluster"
}

# Task Definition
resource "aws_ecs_task_definition" "app" {
  family                   = "my-app"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "512"  # 0.5 vCPU
  memory                   = "1024" # 1GB

  execution_role_arn = aws_iam_role.ecs_execution_role.arn
  task_role_arn      = aws_iam_role.ecs_task_role.arn

  container_definitions = jsonencode([{
    name  = "app"
    image = "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest"

    portMappings = [{
      containerPort = 8080
      protocol      = "tcp"
    }]

    environment = [
      { name = "ENV", value = "production" }
    ]

    secrets = [
      {
        name      = "DATABASE_URL"
        valueFrom = aws_secretsmanager_secret.db_url.arn
      }
    ]

    logConfiguration = {
      logDriver = "awslogs"
      options = {
        "awslogs-group"         = "/ecs/my-app"
        "awslogs-region"        = "ap-northeast-1"
        "awslogs-stream-prefix" = "ecs"
      }
    }
  }])
}

# ECS Service
resource "aws_ecs_service" "app" {
  name            = "my-app-service"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 2
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = var.private_subnet_ids
    security_groups  = [aws_security_group.ecs_tasks.id]
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "app"
    container_port   = 8080
  }

  depends_on = [aws_lb_listener.app]
}

# Auto Scaling
resource "aws_appautoscaling_target" "ecs" {
  max_capacity       = 10
  min_capacity       = 2
  resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_policy" "ecs_cpu" {
  name               = "cpu-autoscaling"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.ecs.resource_id
  scalable_dimension = aws_appautoscaling_target.ecs.scalable_dimension
  service_namespace  = aws_appautoscaling_target.ecs.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageCPUUtilization"
    }
    target_value = 70.0
  }
}
```

**Code volume**: about 80 lines
**Difficulty to understand**: ★★☆☆☆

---

### EKS Setup (Complex)

```hcl
# EKS Cluster
resource "aws_eks_cluster" "main" {
  name     = "my-startup-cluster"
  role_arn = aws_iam_role.eks_cluster.arn
  version  = "1.28"

  vpc_config {
    subnet_ids              = concat(var.private_subnet_ids, var.public_subnet_ids)
    endpoint_private_access = true
    endpoint_public_access  = true
  }

  depends_on = [
    aws_iam_role_policy_attachment.eks_cluster_policy,
    aws_iam_role_policy_attachment.eks_vpc_resource_controller,
  ]
}

# Node Group
resource "aws_eks_node_group" "main" {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = "main-node-group"
  node_role_arn   = aws_iam_role.eks_nodes.arn
  subnet_ids      = var.private_subnet_ids

  scaling_config {
    desired_size = 2
    max_size     = 10
    min_size     = 2
  }

  instance_types = ["t3.medium"]

  depends_on = [
    aws_iam_role_policy_attachment.eks_worker_node_policy,
    aws_iam_role_policy_attachment.eks_cni_policy,
    aws_iam_role_policy_attachment.eks_container_registry_policy,
  ]
}

# IAM Roles（省略：ECS以上に複雑）
# ...

# OIDC Provider（EKSで必須）
data "tls_certificate" "eks" {
  url = aws_eks_cluster.main.identity[0].oidc[0].issuer
}

resource "aws_iam_openid_connect_provider" "eks" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
  url             = aws_eks_cluster.main.identity[0].oidc[0].issuer
}

# AWS Load Balancer Controller（Helmで別途インストール必要）
# Ingress設定（別途K8s YAMLで管理）
# ...
```

Then you separately create Kubernetes manifests (Deployment/Service/Ingress):

```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
        ports:
        - containerPort: 8080
        env:
        - name: ENV
          value: production
        # ...以下50行以上の設定
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
# ...以下複雑な設定
```

**Code volume**: Terraform 150 lines + Kubernetes YAML over 100 lines
**Difficulty to understand**: ★★★★★

---

## Migration Scenario: "When Should You Migrate to EKS?"

### Signals That an ECS → EKS Migration Becomes Necessary

1. **30+ microservices**: ECS management gets cumbersome
2. **A complex service mesh is needed**: leveraging the K8s ecosystem like Istio/Linkerd
3. **A multi-cloud strategy**: GCP/Azure expansion is in view
4. **Custom orchestration**: Operator/CRD development is needed

### The Reality of Migration Cost

- **Duration**: 2–6 months (depending on scale)
- **Cost**: 2 engineers × 3 months = about ¥5 million
- **Risk**: downtime, configuration mistakes, performance degradation

### My Recommended Strategy

**Phase 1 (year 0–2)**: grow fast with ECS on Fargate
**Phase 2 (year 2–3)**: evaluate the scale situation, consider EKS migration if needed
**Phase 3 (year 3+)**: optimize according to business growth

---

## Decision Checklist

### Conditions Where You Should Choose ECS on Fargate (3 or more apply)

- [ ] Your team has 0–1 K8s-experienced people
- [ ] A release within 3–6 months is mandatory
- [ ] The number of microservices is 20 or fewer
- [ ] Monthly PV is 10 million or fewer
- [ ] The AWS-migration possibility is low (<10%)
- [ ] You want to minimize operational cost
- [ ] You prioritize simplicity

### Conditions Where You Should Choose EKS (3 or more apply)

- [ ] Your team has 2 or more K8s-experienced people
- [ ] You have time to spare (6 months or more)
- [ ] The number of microservices is 30 or more
- [ ] You anticipate monthly PV of 50 million or more
- [ ] You have a multi-cloud strategy
- [ ] Leveraging the K8s ecosystem is mandatory (Istio, etc.)
- [ ] You prioritize future extensibility above all

---

## The Result in a Real Product: The Case of the Minister of Economy, Trade and Industry Award-Winning SaaS

### The Adopted Setup

- **Choice**: ECS on Fargate
- **Reason**: team of 2, 3-month release, no K8s experience
- **Scale**: 5 microservices, 500,000 monthly PV

### Outcomes

- **Development period**: succeeded in releasing in 3 months
- **Operational cost**: ¥120,000/month (the entire infrastructure)
- **Availability**: 99.9%+ (annual downtime < 9 hours)
- **Scale handling**: auto-scaling handles sudden traffic spikes automatically

### Evaluation 2 Years Later

- **The ECS choice was correct**: still sufficient with ECS, no EKS migration needed
- **Reduced learning cost**: could invest the K8s learning time into feature development
- **Operational load**: stable operation with about 5 hours/week of operations

---

## Summary: The Essence of the Decision

### 3 Important Principles

1. **Prioritize "now's" business constraints**: "future scale" may be an illusion
2. **Learning cost and operational cost are true costs**: don't judge by infra fees alone
3. **Migration is possible**: ECS → EKS is feasible, and it's not too late to decide later

### My Recommendation

**Startup (seed to Series A)**: strongly recommend **ECS on Fargate**
- Reason: fast release, low operational load, sufficient scalability

**Mid-sized company (complex requirements)**: evaluate individually
- Has K8s-experienced people → consider EKS
- Doesn't → start with ECS

**Enterprise**: EKS
- Reason: advanced control, multi-cloud, ecosystem leverage

---

## Next Steps

Use the **7 evaluation axes** provided in this article to make the optimal choice for your project.

If you're troubled over technology selection or architecture design, feel free to consult me. I'll bring the practical knowledge cultivated in developing the Minister of Economy, Trade and Industry Award-winning product to bear on your project.

[Contact here](/contact)

---
