Updated Nov 5, 20267 min read

AWS Scaling for Backends: Auto Scaling, Target Tracking and Cost Control

How EC2 Auto Scaling groups, ECS service auto scaling, target tracking and scheduled scaling work for a backend, where cost leaks, and how to run services that scale in your own AWS account from application code.

AWS scaling is how a backend keeps up with traffic without you editing desired counts by hand. On virtual machines that is an EC2 Auto Scaling group. On containers it is ECS service auto scaling through Application Auto Scaling. Both lean on target tracking, and both burn money when minimums, metrics or cooldowns are wrong.

This guide covers the controls that matter for a product API, the cost mistakes that show up in the bill, and how Encore (infrastructure from code) runs those services in your account so sizing lives next to the app.

AWS scaling at a glance

Encore (Fargate in your account)EC2 Auto ScalingECS service auto scaling
Unit that scalesFargate tasks for your servicesEC2 instances in an ASGDesired task count on a service
Common policySize and process allocation in the dashboardTarget tracking on CPU or ALB requests per targetTarget tracking on CPU, memory or custom metrics
Scheduled capacityEdit environment settingsScheduled actions on the ASGScheduled actions via Application Auto Scaling
Idle cost riskRunning tasks keep billingMinimum instances stay upMinimum tasks stay up
Local feedbackLocal infrastructure from the same codeYou build itDocker Compose or similar

EC2 Auto Scaling groups

An Auto Scaling group keeps a fleet of instances between a minimum and maximum size, using a launch template for AMI, instance type and user data. Target tracking is the default policy shape: you set a target such as 50 percent average CPU, and Auto Scaling creates the CloudWatch alarms that add or remove instances.

Predefined metrics include ASGAverageCPUUtilization, network in/out, and ALBRequestCountPerTarget. For ALB request count you pass a ResourceLabel that identifies the target group. Target tracking prioritizes availability: it scales out if any policy says so, and scales in only when every policy with scale-in enabled agrees. New instances have a warmup period during which they do not count toward the metric, which stops the group from thrashing during deploys.

Step scaling still exists when you need fixed increments at alarm thresholds. Most HTTP backends start with target tracking on CPU or requests per target and only reach for step policies when the metric is spiky or queue-backed.

ECS service auto scaling

ECS does not scale by replacing instances when you use Fargate. It changes how many tasks the service should run. Application Auto Scaling supports target tracking, step scaling, scheduled actions, predictive scaling and custom backlog-per-task metrics for SQS workers.

ECS publishes average CPU and memory utilization every minute. Target tracking on CPU is the usual starting point for an API. For workers, a custom metric of queue depth divided by running tasks tracks load better than CPU, because an idle poller looks quiet while the backlog grows. You can set minimum capacity to 0 when a worker should disappear with an empty queue; target tracking then waits for a data point before scaling out from zero.

During a deployment, Application Auto Scaling turns off scale-in but leaves scale-out active, so a rollout does not shrink the service under you. Cooldown periods stop a noisy metric from adding tasks every minute. On the EC2 launch type you also need cluster capacity (a capacity provider and an ASG) or tasks sit pending with nowhere to land.

Scheduled scaling and predictable peaks

Scheduled actions set min, max or desired capacity at a wall-clock time. Application Auto Scaling uses a six-field cron expression and an IANA time zone, for example every weekday at 08:00 before business traffic. EC2 Auto Scaling has its own scheduled action API with classic cron syntax.

Scheduled scaling fits known peaks: markets open, nightly batch windows, marketing launches. It fails when the calendar is wrong or traffic shifts and nobody updates the schedule. Pair it with target tracking so an unexpected spike still gets capacity, and set the schedule's floor high enough that cold starts or task pull time do not eat the first minutes of the peak.

Cost pitfalls

Minimum capacity is a common hidden cost: an ASG with min=3 or an ECS service with desired=3 never returns to zero at night. Target values that are too low (for example 20 percent CPU) keep extra instances warm "just in case" and look like reliable scaling until finance asks why staging costs as much as production.

Other common leaks: detailed monitoring and high-resolution metrics you forgot you enabled, scale-out without a matching scale-in policy, Fargate tasks oversized on CPU or memory relative to actual p95 usage, and separate Auto Scaling paths for every microservice that could have shared a process. Predictive scaling and multiple overlapping policies can also fight each other if two metrics disagree about load.

How does Encore run services that scale in your AWS account?

Encore

Encore combines an open source infrastructure SDK for TypeScript and Go with a platform that provisions and deploys into your own AWS or GCP account. On AWS, services run on Fargate (or EKS if you choose it) behind an Application Load Balancer. Encore creates the task definitions, services and networking from what the code declares, and Encore provisions an IAM role for the service.

The Infrastructure page in the Encore dashboard with a database's configuration panel open, showing fields for vCPUs, memory, storage, availability type, max connections and backups.
Each provisioned resource can be reviewed and its configuration edited per environment in the Encore dashboard. The screenshot shows a GCP Cloud SQL database.

Set up the app

Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

~
$ encore app create traffic --example=ts/empty$ cd traffic && mkdir api

A small API with Redis-backed caching is enough to see the shape. The scaling knobs for the database and how services share processes live in the environment, not in a second Terraform stack:

// api/encore.service.ts import { Service } from "encore.dev/service"; export default new Service("api");
// api/api.ts import { api } from "encore.dev/api"; import { CacheCluster, IntKeyspace } from "encore.dev/storage/cache"; const cluster = new CacheCluster("api-cache", { evictionPolicy: "allkeys-lru", }); const hits = new IntKeyspace<{ path: string }>(cluster, { keyPattern: "hits/:path", }); export const ping = api( { expose: true, method: "GET", path: "/ping" }, async (): Promise<{ ok: boolean; pathHits: number }> => { const pathHits = await hits.increment({ path: "ping" }, 1); return { ok: true, pathHits }; }, );

encore run starts the service with a local in-memory cache so you can exercise the endpoint before deploying, as described in the caching docs. On deploy, Encore provisions the Fargate service, the load balancer path and ElastiCache for Redis in your account, and provisions an IAM role for the service. Connecting the account is covered in the own-cloud guide. In the infrastructure configuration UI you pick compute (Fargate or EKS), database sizing and process allocation: one process for all services, or one process per service. One process cuts idle cost and latency between services; separate processes isolate blast radius in production.

Encore updates resources with PATCH-style changes that modify only the attributes that need to change. Before changing a resource it reads the current properties, and when a setting was changed directly in the cloud console it updates its own representation to match, unless a change requested in the dashboard is still pending, as described in managing infrastructure.

An AI coding agent can add the cache or a second service in the same change and leave cloud sizing to the environment settings you already reviewed.

Best fit: Teams who want backends on Fargate in their own AWS account, with resource sizing and process allocation in the Encore dashboard.

Which controls to use when

GoalControl
Hold steady CPU or request rate on instancesEC2 target tracking on the ASG
Hold steady CPU or memory on containersECS target tracking on the service
Known weekday or event peaksScheduled scaling, plus target tracking for surprises
Queue workers that should idle at zeroMinimum capacity 0 and a backlog-per-task metric
App infrastructure and baseline capacity from codeEncore on Fargate

Frequently asked questions

What is AWS Auto Scaling for a backend?

AWS Auto Scaling adjusts capacity to match load. On EC2 that means an Auto Scaling group changing the number of instances. On ECS it means Application Auto Scaling changing the desired task count for a service. Target tracking keeps a metric near a value you set, such as average CPU or ALB requests per target.

What is target tracking scaling?

Target tracking is a policy where you pick a metric and a target value, and AWS creates and manages the CloudWatch alarms that scale out or in to hold that average. On EC2 Auto Scaling, common metrics include ASGAverageCPUUtilization and ALBRequestCountPerTarget. On ECS, services commonly track average CPU or memory utilization.

How do I scale an ECS service on Fargate?

Register the service as a scalable target with Application Auto Scaling, then attach a target tracking, step, scheduled or predictive policy. ECS publishes CPU and memory utilization metrics every minute. Set a minimum and maximum task count so scale-in cannot drop below what you need for availability.

How do I scale a TypeScript backend on AWS with services sized from one place?

With Encore, define services with api() and deploy to an AWS environment on Fargate. Encore creates the Fargate services and load balancer in your account. Size databases and choose process allocation per environment in the dashboard. Settings changed directly in the AWS console are detected as drift before the next change is applied.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders