Use when it fits · AWS · Steady HTTP core

Fargate services (always on)

A container that runs all the time behind a load balancer. Where a Lambda goes once it's busy all day.

Lambda is my default, and a Fargate service is where a Lambda goes when it has stopped being spiky. The signal isn't a high reserved concurrency, which costs nothing. It's concurrency that stays high all day: an API that waits on Postgres pays Lambda for every millisecond of that wait, request by request, while one container serves many of them at once.

The numbers are in Lambda, Fargate or EC2?: at 50 requests in flight all day, about $1,883 a month on Lambda against about $437 on Fargate. At 5, the saving doesn't pay for the container. So I move only the steady HTTP core, measured first, and keep events, queues, schedules and spikes on Lambda.

How I'd wire it: ECS Express Mode on Fargate, Arm, one Node.js service, the domain on a Worker or CloudFront in front so the move is an origin change, and a Compute Savings Plan once three months show the floor.

Use it when

  • One HTTP function's concurrency stays at about 10 or more all night, or averages 30% of its daily peak, and its Lambda bill passes about $500 a month.
  • The service mostly waits on Postgres or other APIs: one Node.js process serves many requests at once, where Lambda bills each one for its whole wait.
  • A hard Lambda limit hits: requests over 15 minutes, long-lived connections, more than 10 GB of memory, or Postgres running out of connections.

Don't use it when

  • Traffic is spiky, with a daily average a tenth of its peak or less: Lambda scales in seconds and costs nothing in between. Sized for a ten-minute peak, a container runs it all day.
  • Events, queues and schedules: they stay on Lambda (or a Fargate scheduled task for long jobs).
  • The saving would be under about $300 a month: it doesn't pay for owning a load balancer, scaling and deploys.

Pricing

Per second of vCPU and memory, around the clock. Sydney, Arm: $0.03885 per vCPU-hour and $0.00426 per GB-hour (x86: $0.04856 and $0.00532). A 1 vCPU / 2 GB Arm task is about $34.58 a month. Add the Application Load Balancer ($18.40 a month plus about $5.84 per capacity unit) and $3.65 a month per public IPv4 address: the smallest highly available setup, two small tasks in two zones, is about $73 a month. Compute Savings Plans take 21% (1 year) to 46% (3 years) off Fargate on Arm.

Gotchas, with fixes

Gotcha: Target-tracking scaling reacts on one-minute metrics with a cooldown, then new tasks must start: a sudden ten-minute peak is mostly over before the capacity arrives.

Fix: Keep the spiky part on Lambda, or use scheduled scaling when the peak's time is known.

Gotcha: Tasks in private subnets need a NAT gateway to reach ECR, Neon or any API: about $43 a month before data, for every zone.

Fix: Run tasks in public subnets with public IPs and a security group that only accepts the load balancer, or add VPC endpoints when they must stay private.

Gotcha: App Runner, the easy way to run a container service, is closed to new customers.

Fix: Use ECS Express Mode: one call creates the Fargate service, the load balancer with TLS, health checks and scaling, at no extra charge.

Provisioning

Official Pulumi package · Official Terraform provider

aws.ecs.Service, TaskDefinition and an Application Load Balancer in @pulumi/aws (awsx.ecs.FargateService wraps them). ECS Express Mode creates all of it in one call; its Terraform support is official.

Instead, consider

Worked examples

Sources

Last reviewed by Nicolas Dao

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: