TOPIC: AWS ECS Fargate for startups
URL SLUG: /blog/aws-ecs-fargate-startup-first-service
META TITLE: AWS ECS + Fargate for Startups: Deploy Your First Service Without Reading the Docs
META DESCRIPTION: Deploy a containerized app to ECS Fargate without wading through AWS documentation. VPC, ALB, auto-scaling — here's what startups actually need to know to ship to production.
AWS ECS + Fargate for Startups: Deploy Your First Service Without Reading the Docs
AWS ECS Fargate is excellent infrastructure for startup teams that have outgrown Railway or Render. It's also surrounded by enough documentation that most engineers spend two days reading and come out less confident than when they started.
This guide skips the theory. You get the decisions that matter, the setup that works, and the traps to avoid — in the order you'll actually encounter them.
You don't need to understand every ECS concept to ship to production. You need to understand the six things below.
What You're Actually Building
Before touching anything, here's the mental model:
ECS is the thing that manages your containers. It decides how many should be running, where they run, whether they're healthy, and what to do when one crashes. Fargate is the compute layer underneath ECS — it's where the containers actually run. You don't manage the servers. Fargate does.
The full stack for a typical startup service looks like this:
Internet → Application Load Balancer → ECS Service → Fargate Tasks (your containers)
↓
RDS (Postgres) / ElastiCache (Redis)
Everything in this diagram lives inside a VPC — your isolated network environment on AWS. The ALB is the only thing exposed to the internet.
Step 1: Get Your VPC Right First
Everything else depends on this. A bad VPC setup means networking headaches later that are hard to untangle.
For a startup, the setup you want is:
- One VPC with a clean CIDR block (e.g.,
10.0.0.0/16) - Two public subnets (one per AZ) — for your ALB
- Two private subnets (one per AZ) — for your Fargate tasks and databases
- NAT Gateway in one AZ — lets private subnet resources reach the internet (for pulling images, hitting APIs)
Your Fargate tasks should run in private subnets. The ALB sits in public subnets and routes traffic in. Your databases should never have a public IP.
If you're on NoahOps, this VPC is provisioned for you per environment (production, staging, preview). If you're building this yourself, use the VPC creation wizard in the AWS console with the "VPC with public and private subnets" template — it gets the routing tables right automatically.
Step 2: Write Your Task Definition
A task definition tells ECS what your container needs to run: image, CPU, memory, environment variables, port, and log configuration. Here's a minimal working example:
{
"family": "my-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::YOUR_ACCOUNT:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "api",
"image": "YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-api:latest",
"portMappings": [{ "containerPort": 3000 }],
"environment": [
{ "name": "NODE_ENV", "value": "production" }
],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:my-api/db-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
A few things worth flagging here:
networkMode: awsvpc is required for Fargate. Each task gets its own network interface and IP. Security groups apply at the task level, not the instance level.
Never put secrets in environment variables. Use AWS Secrets Manager with the secrets field. ECS injects the value at runtime. Your database password never touches your task definition, your code repo, or your CI logs.
executionRoleArn is not the same as taskRoleArn. The execution role is what ECS uses to pull your image from ECR and fetch secrets. The task role is what your application code uses to call AWS services. You need both. Most getting-started guides conflate them, which causes permissions errors later.
Step 3: Set CPU and Memory Realistically
Fargate uses fixed CPU/memory combinations. The most common trap for startup teams: over-provisioning because it "feels safer" and then being surprised by the bill.
For a typical Node.js or Python API:
| Workload | CPU | Memory | |---|---|---| | Background worker, low traffic | 256 (.25 vCPU) | 512 MB | | API service, moderate traffic | 512 (.5 vCPU) | 1 GB | | API service, heavier traffic | 1024 (1 vCPU) | 2 GB | | Data processing | 2048 (2 vCPU) | 4 GB |
Start at the lower end and watch your CloudWatch metrics for CPU utilization and memory utilization. Resize up if you see sustained high utilization. Fargate bills per second, so right-sizing has a direct cost impact.
If you're running Linux on ARM (Graviton), you get roughly 20% better price-performance for the same spec. If your Docker image supports linux/arm64, it's worth switching.
Step 4: Put an ALB in Front of Everything
Don't expose Fargate tasks directly to the internet. Run an Application Load Balancer in your public subnets and route traffic to a target group that contains your ECS service.
The ALB does four important things:
-
Terminates HTTPS. Your containers serve HTTP on port 3000 (or whatever). The ALB handles the TLS certificate and forwards plain HTTP internally. One cert, one place to manage it.
-
Health checks. The ALB checks your
/healthendpoint every 30 seconds. If a task is unhealthy, it stops routing traffic to it and ECS replaces it. -
Zero-downtime deploys. ECS runs the new task, waits until it passes health checks on the ALB, then drains and terminates the old task. You don't need blue/green or any extra orchestration for this.
-
Path-based routing. If you're running multiple services, one ALB can route
/api/*to one ECS service and/admin/*to another — you pay for one ALB instead of one per service.
Step 5: Configure Auto-Scaling Before You Need It
ECS Application Auto Scaling lets you define how the service should scale based on CPU or memory utilization. Set this up before launch — it takes five minutes and saves you from a 2am scramble when traffic spikes.
A simple setup for a startup API:
- Minimum tasks: 2 (gives you redundancy across AZs)
- Maximum tasks: 10 (or whatever your budget supports)
- Scale-out trigger: average CPU > 70% for 2 minutes → add 2 tasks
- Scale-in trigger: average CPU < 30% for 10 minutes → remove 1 task
Scale-in should be conservative (longer window, smaller step). Scale-out should be aggressive (short window, meaningful step). Scaling down too fast causes thrashing — adding and removing tasks in response to normal traffic variation.
If you have predictable traffic patterns (e.g., heavy daytime usage, near-zero overnight), Scheduled Scaling lets you set task counts on a schedule rather than waiting for CPU to spike.
Step 6: Manage Secrets Properly From Day One
The most common security gap in startup AWS setups: database credentials and API keys in environment variables, committed to the repo or visible in the ECS task definition.
The correct pattern:
- Store secrets in AWS Secrets Manager (or Parameter Store for non-sensitive config)
- Reference them in your task definition using the
secretsfield (notenvironment) - Grant your task execution role permission to access those specific secrets
- Rotate secrets using Secrets Manager's rotation feature — your tasks pick up new values on restart without any code changes
This costs ~$0.40/secret/month. It's the cheapest security decision you'll make.
What You Don't Need to Set Up
Skip these unless you have a specific reason to add them:
AWS Copilot or CDK for your first service. Both are worth learning. Neither is worth the overhead when you're shipping your first Fargate service. Get something running via the console or CLI first, then move to infrastructure-as-code.
Multi-AZ NAT Gateways. One NAT Gateway in one AZ is fine for a startup. NAT Gateways cost ~$32/month each. Multi-AZ adds resilience but doubles the cost. Add the second one when your compliance requirements or SLA commitments make it necessary.
EKS. Kubernetes is overkill for most startup infrastructure. ECS Fargate handles 95% of startup workload patterns without the operational overhead of running a Kubernetes control plane. Start with ECS; migrate to EKS only when you have specific Kubernetes requirements that matter to your engineers.
The Thing That Trips Most Teams Up
ECS Fargate is genuinely straightforward once it's running. The part that causes most of the confusion is IAM — specifically, the difference between:
- Execution role: what ECS uses to start your task (pull image from ECR, fetch secrets)
- Task role: what your application code uses at runtime (read from S3, write to SQS, etc.)
A task without a task role can't call any AWS services from application code. A task without a properly configured execution role won't start. Both need to exist. Both need the right policies attached. Getting this wrong is the most common reason Fargate tasks fail to launch.
FAQ
Do I need ECS Express Mode?
If you're starting fresh in 2026, yes — use it. ECS Express Mode simplifies the initial service creation significantly. It creates real ECS resources under the hood, so you're not locked into anything, and you can modify the underlying resources directly if you need to.
How much does a basic Fargate setup cost for a startup?
A minimal production setup — 2 tasks at 0.5 vCPU / 1 GB, one ALB, one small RDS instance — runs roughly $80–120/month depending on region and traffic. Fargate Spot for non-critical workloads (workers, batch jobs, staging) cuts compute costs by up to 70%.
Should my Fargate tasks run in public or private subnets?
Private subnets, always. Public subnets expose your tasks directly to the internet. Traffic should enter via the ALB in a public subnet, not directly to your tasks.
How do rolling deploys work on Fargate?
ECS starts new tasks with the new image, waits until they pass health checks on the ALB, then drains connections from old tasks and terminates them. No downtime if your health check endpoint is reliable and your deregistrationDelay is set appropriately (60–90 seconds is typical).
What's the difference between ECS and EKS for a startup?
ECS is simpler to operate, integrates natively with the AWS ecosystem, and handles the vast majority of startup workload patterns. EKS (Kubernetes) offers more portability and ecosystem tooling but adds significant operational complexity. Default to ECS unless you have engineers who specifically want Kubernetes or workloads that benefit from Kubernetes-specific features.
Rather not configure all this yourself? Request a free demo at noahops.com — NoahOps provisions isolated VPC environments, ECS Fargate services, managed RDS, and Redis with CI/CD wired up, so your first production service is live in minutes, not days.