Back to resources
// architecture · scaling

Scale without blowing the budget

Absorbing ten times the traffic doesn't force you to pay ten times more, nor all the time. The sequel to my e-commerce architecture: how I size to ride a spike, then come back down — without leaving the bill up there.

GuideJul 13, 2026~8 min · intermediate
ALBAuto ScalingRDS replicasElastiCacheCloudFront
01

The starting point

We start from the e-commerce architecture: EC2 for the site, RDS for the database, S3 + CloudFront for images. To scale, you don’t grow one machine forever — you put several behind a load balancer, and offload the database.

// the path of a request
Visitor
client
CloudFront
CDN
EC2
web · PHP/Next
RDS
database
S3
product photos
Lambda
→ WebP + sizes
CloudFront also serves the images from S3
i

If you haven’t read the foundation, start with why AWS for an e-commerce — this article is its direct sequel.

02

Scale up then back down

The key to controlled cost is elasticity: add instances when traffic rises, remove them when it falls. You only pay for peak capacity during the peak.

autoscaling.tfcopy
# auto-scaling : grossir au trafic, redescendre ensuite
resource "aws_autoscaling_policy" "cpu" {
name = "scale-on-cpu"
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 60.0 # vise 60% de CPU : au-dela, on ajoute une instance
}
}
01
Load balancer

An ALB spreads traffic over N instances and automatically drops those failing the health check.

02
Auto-scaling

Rules on CPU (or request queue) add/remove instances. Min 2 for resilience, max capped for budget.

03
Read replicas

Reads (catalog, product pages) go to RDS replicas; the primary keeps writes (orders).

04
Cache

ElastiCache/Redis absorbs what’s read on repeat. The cheapest query is the one you don’t run.

03

Offload the database

The database is almost always the first bottleneck. Before adding web servers, cache what’s read on repeat — often 80% of queries hit 20% of the data.

cache.tscopy
// soulager la base : mettre en cache ce qui est lu en boucle
const cached = await redis.get(key);
if (cached) return JSON.parse(cached); // pas de requete DB
const rows = await db.query("SELECT ..."); // fallback base
await redis.set(key, JSON.stringify(rows), "EX", 60);
return rows;
!

The trap: over-provisioning “just in case” and leaving it running. Set a reasonable auto-scaling max and monitor — otherwise a looping bug can explode the bill overnight.

04

Keep cost tied to traffic

Stable baseline on Savings Plans (the min 2 instances), peak on on-demand: you commit only on the predictable.
CloudFront in front of all static: fewer calls reach the EC2.
Auto-scaling that actually scales down at night — check the metrics, not just the config.
i

Scaling and cost are two sides of the same coin. The playbook to deflate what has drifted: cut an AWS bill in half.

05

Which scaling policy to pick

“Auto-scaling” isn't one button. There are several ways to trigger adding instances, and the choice changes behavior during a spike. On my e-commerce architecture I almost always start from target tracking: I set a target — say 50% average CPU, or a request count per instance — and EC2 Auto Scaling creates and manages the CloudWatch alarms itself to hold that target. AWS explicitly recommends it for scaling on average CPU or request count per target.

Target tracking

My default

You give a target (50% CPU), AWS manages the alarms and aims for that number — like a thermostat.
It scales in more gradually than it scales out: the priority is availability, not aggressive scale-down.
Recommended metric: ALBRequestCountPerTarget, which tracks real load better than CPU for web workloads.
Step scaling

Fine control

You define steps: +1 instance past a threshold, +3 if load truly spikes.
Useful when the reaction must be proportional to how far the breach goes.
More manual wiring: you own the CloudWatch alarms yourself.
i

A detail that trips many people up: cooldown only applies to simple scaling policies. Target tracking and step scaling can start a scale-out immediately — it's the instance warmup (the time for a new machine to become healthy) that paces things, not a fixed cooldown. AWS now steers away from simple scaling policies in favor of target tracking.

Anticipating the predictable spike: predictive scaling

Target tracking is reactive: it waits for CPU to climb before acting, and a fresh instance takes a minute or two to boot. For a spike I can see coming — Monday-morning sale, a 6pm campaign — I add predictive scaling. It analyzes up to 14 days of history, derives an hourly 48-hour forecast, and provisions before the load lands. Two things to remember: it starts in “forecast only” mode (it forecasts without scaling, so you can validate first), and it only scales out — to come back down you keep your dynamic policies. Predictive handles the predictable, target tracking absorbs the unexpected on top.

!

For read replicas there's no equivalent magic: RDS does not autoscale replicas. You add and remove them by hand, and each replica is billed as an instance of its class. That's exactly why cache comes first: adding a replica is a fixed cost that won't quietly fall back at night.

06

The economics of hit ratio

A cache is only worth its hit ratio: the share of requests served from cache instead of from the origin. That number isn't cosmetic — it drives the bill directly. At 80% hit, only one request in five reaches the database or EC2; at 95%, it's one in twenty. Going from 80% to 95% isn't “15% better”: it quarters the load that lands behind — potentially one fewer read replica, or two fewer EC2 instances during the peak.

80% hit
20% origine atteinte
90% hit
10% origine atteinte
95% hit
5% origine atteinte
99% hit
1% origine atteinte

In practice there are two caches to watch. On ElastiCache/Redis, the AWS guide on which metrics to monitor recommends alarming on evictions and memory: when Redis evicts keys for lack of room, your hit ratio drops and the database eats it all again. In front of static assets, CloudFront has its own lever: increase the cache hit ratio by lengthening max-age, trimming the query strings and cookies pulled into the cache key, and enabling Origin Shield as an extra layer in front of the origin.

ElastiCacheAim for a hit ratio ≥ 80%; watch Evictions and FreeableMemory, or the cache works against you.
CloudFrontLong max-age on static, minimal cache key, Origin Shield for large image catalogs.
Warm poolIf your instances boot slowly, a [warm pool](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) keeps pre-initialized machines in the Stopped state — you then pay only for EBS, not compute.

The right loop: measure the hit ratio first, then decide. Often, gaining 10 points of hit costs nothing (just config) and spares you from adding hardware that bills 24/7.

07

Sources & further reading

01AWS — Target tracking scaling policiesThe policy I take by default: CPU/request target, alarms managed by AWS.02AWS — Step and simple scaling policiesStep adjustments, for when you want a reaction proportional to the breach.03AWS — Scaling cooldownsWhy cooldown only applies to simple scaling, not target tracking.04AWS — How predictive scaling works48h forecast from history, forecast-only mode to validate first.05AWS — Warm pools for Auto ScalingPre-initialized Stopped instances to absorb a spike without paying for idle compute.06AWS — RDS read replicasScale reads; key reminder: no autoscaling of replicas, it's manual.07AWS — ElastiCache: which metrics to monitorAlarm on evictions and memory to protect the hit ratio.08AWS — Increase CloudFront cache hit ratiomax-age, minimal cache key, Origin Shield: more hit, less origin.

Scaling cleanly means making cost proportional to traffic: several instances behind a load balancer, a database offloaded by cache and replicas, and auto-scaling that actually scales down. You ride the spike, and the bill falls back with it.