Auto Scaling and Elasticity: EC2, Caching, and Database Scaling
Elasticity is the ability of a workload to add capacity automatically when demand rises and shed it when demand falls, keeping performance steady without paying for idle resources. Task 2.1 of the SOA-C03 exam tests whether you can operate that machinery: EC2 Auto Scaling groups and their policy types, the metrics those policies track, warmup, cooldown and scale-in controls, scaling for ECS services and Lambda functions, the caching layers (CloudFront and ElastiCache) that absorb load before it reaches your compute, and the scaling controls built into RDS, Aurora and DynamoDB. The questions are operational, not architectural: a group that launches and terminates instances in a loop, an alarm in breach with nothing launching, a cache whose hit rate keeps falling, a read replica falling behind, a DynamoDB table throttling writes. This lesson works through the scaling mechanisms for the compute, cache and database tiers, compares the near-twin controls the exam likes to set against each other, and walks through the troubleshooting patterns its scenarios come from.
On this page11 sections
- How an EC2 Auto Scaling group keeps capacity right
- Scaling policy types compared
- Choosing the metric for target tracking
- Cooldowns, instance warmup, and lifecycle hooks
- Controlling scale-in: protection, termination policies, and termination hooks
- Troubleshooting: flapping, stuck at max, and suspended processes
- Scaling beyond EC2: ECS services and Lambda
- Caching for dynamic scalability: CloudFront and ElastiCache
- ElastiCache topology, metrics, and scaling
- Scaling RDS and Aurora
- Scaling DynamoDB: capacity modes and throttling
- Configure EC2 Auto Scaling groups with launch templates, min/max/desired capacity, health-check type and grace period
- Choose the right scaling policy (target tracking, step, simple, scheduled or predictive) and the right metric for it, including request count per target and SQS backlog per instance
- Explain how instance warmup, the default cooldown, scale-in protection, termination policies and lifecycle hooks interact
- Diagnose flapping, stuck-at-max capacity, launch failures and suspended processes in an Auto Scaling group
- Scale ECS services across both the task and the instance layer, and choose between Lambda reserved and provisioned concurrency
- Use CloudFront cache policies, Origin Shield and ElastiCache (Valkey, Redis OSS, Memcached, Serverless) to offload traffic, and read cache metrics such as Evictions and EngineCPUUtilization
- Scale RDS, Aurora and DynamoDB with instance class changes, storage autoscaling, read replicas, the right Aurora endpoint, capacity modes and DAX
How an EC2 Auto Scaling group keeps capacity right
An EC2 Auto Scaling group (ASG) keeps a fleet of instances between three numbers: min, max and desired capacity. Scaling policies move desired up and down within the min/max bounds, and the group launches or terminates instances until the running fleet matches it. Note what each bound does: min is a floor that blocks scale-in below it, and max is a ceiling that blocks scale-out above it. A group whose desired capacity equals its minimum can still scale out freely.
What gets launched is defined by a launch template (AMI, instance type, security groups, key pair, user data). Templates are versioned, so you roll a new AMI forward by pointing the group at a new version and roll back just as easily. Launch templates replaced the older launch configurations, which cannot be edited and no longer receive new features. A mixed instances policy lets one group launch several instance types (and Spot as well as On-Demand), which matters when a single type runs short of capacity. Spot allocation strategies such as capacity-optimized can only choose among the pools you allow, so they cannot help a group that lists one instance type in one Availability Zone.
The group also replaces unhealthy instances. By default it uses EC2 status checks: an instance that fails them is terminated and replaced. Behind a load balancer, add the ELB health check type so an instance whose application is broken (but whose VM is fine) is replaced too. The health-check grace period is the time after launch before the group starts acting on a new instance's health checks. Set it shorter than the application's real startup time and the group terminates instances that were still booting, then launches replacements that suffer the same fate.
| Control | What it affects | Side effect |
|---|---|---|
| ASG health-check grace period | Only newly launched instances, for a fixed time after launch | None on running instances; failures are still caught quickly once the instance is in service |
| Target group unhealthy threshold | Every registered target, all the time | Slows detection of real failures across the whole fleet |
So for slow-starting instances, lengthen the grace period rather than loosening the target group's health check. AZ rebalancing keeps instances spread evenly across the group's Availability Zones, launching in an underweighted zone before terminating from an overweighted one. Which instances leave during scale-in is covered in its own section below.
Scaling policy types compared
Five policy types adjust desired capacity, and each answers a different kind of requirement.
| Policy type | How it works | When it's the answer |
|---|---|---|
| Target tracking | You set a target value for a metric (for example, average CPU at 50%); AWS creates and manages the CloudWatch alarms and scales in both directions to hold the target | "Keep a metric near a value": the default, least configuration |
| Step scaling | Your CloudWatch alarm triggers adjustments sized to how far the metric breached: a small breach adds one instance, a large breach adds four | Different responses at different severity levels |
| Simple scaling | One alarm, one fixed adjustment, then the policy waits for the activity to finish and the cooldown to expire before it can act again | Rarely: it is the legacy option and lags fast-moving load |
| Scheduled actions | Set min, desired and/or max at a specific time or on a recurring (cron) schedule | Fixed, known cycles: a weekday 9 a.m. ramp, an overnight scale-down |
| Predictive scaling | Forecasts load from the group's history and launches capacity ahead of the forecast | Recurring daily or weekly patterns, especially with slow-booting instances |
Target tracking is the modern default. Policies can coexist on one group. When several dynamic or predictive policies evaluate at once, the group follows the one calling for the most capacity. A scheduled action is different: it sets capacity values once, so pair it with target tracking by having it raise the minimum (see below).
Scheduled actions: set the floor, not just desired
A scheduled action that only raises desired capacity is overruled as soon as a dynamic policy sees the metric below target: target tracking scales the group back in, sometimes before the peak arrives. To pre-warm for a known event, have the scheduled action raise min (the floor dynamic policies respect), then add a second scheduled action that lowers min again after the peak so normal scale-in can resume.
Predictive scaling in practice
Predictive scaling learns from the group's own load history (it needs at least 24 hours of data to start forecasting and works best on clear daily or weekly cycles) and creates capacity before the forecast load arrives. It has two modes: forecast only, which produces forecasts you can compare with actual load without changing capacity, and forecast and scale, which acts on them. Starting in forecast only mode, alongside the existing dynamic policy, is how you gather evidence before trusting it. A scheduling buffer tells it to launch instances that many seconds before the forecast need, so instances with long boot times are ready in time. Compared with scheduled actions, predictive scaling follows a peak whose time or size drifts from week to week, while a scheduled action fires at the clock time you wrote, whatever the load does. Keep a target tracking policy alongside for load the forecast did not predict.
Choosing the metric for target tracking
Target tracking only works when the metric falls as capacity is added and rises as capacity is removed. Average CPU does that for CPU-bound fleets, but other workloads need a different metric.
| Workload | Metric to track | Why |
|---|---|---|
| CPU-bound fleet | ASGAverageCPUUtilization | Average CPU falls as instances are added |
| I/O-bound or downstream-bound web fleet behind an ALB (CPU stays low while latency climbs) | ALBRequestCountPerTarget | Requests per healthy target falls as targets are added; set the target to what one instance serves well |
Same fleet, using the load balancer total RequestCount | Not suitable | The total does not change when you add instances, so the policy keeps scaling out |
| Workers pulling from an SQS queue | Backlog per instance (metric math) | Queue length alone does not fall in proportion to the number of workers |
Backlog per instance is the AWS-recommended metric for queue workers. Build it with metric math: the queue's ApproximateNumberOfMessagesVisible divided by the group's GroupInServiceInstances. The target is a number of messages, not seconds: the acceptable wait time divided by the average processing time per message. For example, if a message may wait at most 120 seconds and each takes 4 seconds to process, one instance can work through a backlog of 30 messages in time, so the target is 30. Target tracking then adds workers whenever each instance has more than 30 messages waiting. Setting the target to the wait time itself confuses seconds with messages.
Cooldowns, instance warmup, and lifecycle hooks
Cooldowns and warmup exist because a freshly launched instance contributes nothing for its first minutes, and scaling decisions made during that window overreact. The two settings apply to different policy types.
| Setting | Applies to | What it does |
|---|---|---|
| Default cooldown (300 seconds unless changed) | Simple scaling only | After a scaling activity completes, the simple policy waits for the cooldown before acting again. Even with a cooldown of 0 it still waits for the current activity to finish. |
| Instance warmup (set it as the group's default instance warmup) | Target tracking and step scaling (and instance refresh) | A new instance's metrics stay out of the group's aggregated metrics until warmup ends, while the instance already counts toward the capacity the policy has added |
This is why changing the default cooldown has no effect on a target tracking group that overshoots: the setting that matters there is instance warmup. Set warmup to roughly the time an instance takes to boot and start serving. During warmup, the group neither scales out again for load the new instance is about to absorb nor treats the booting instance's near-zero CPU as a reason to scale in. Step scaling also keeps responding while an activity is in progress (a bigger breach can trigger a further step), whereas simple scaling cannot act again until its activity and cooldown are both over. Warmup is a different knob from the health-check grace period: grace delays health evaluation; warmup delays metric participation.
Lifecycle hooks pause an instance mid-transition. A launch hook holds a new instance in Pending:Wait so you can install software, register it with tooling or pre-warm a local cache before it goes into service; a termination hook holds it in Terminating:Wait so you can drain work and ship logs off the box. If a group launches instances that hang before entering service, an uncompleted launch hook is a prime suspect. The termination side, and how long a hook can hold an instance, is covered next.
Controlling scale-in: protection, termination policies, and termination hooks
When a group scales in, three controls decide what happens, and they act at different points: scale-in protection decides whether an instance can be chosen, the termination policy decides which eligible instance is chosen, and a termination lifecycle hook decides how long the chosen instance waits before it terminates.
| Control | Acts | Use it when |
|---|---|---|
| Instance scale-in protection | Before selection: protected instances are left out of scale-in | An instance is doing long-running work that must not be cut off; the worker sets protection when a job starts and clears it when idle |
| Termination policy | During selection: picks which unprotected instance goes | You want a particular kind of instance removed first |
| Termination lifecycle hook | After selection: holds the chosen instance in Terminating:Wait | You need time to drain connections, finish a short job or copy logs before the instance goes |
Scale-in protection does not stop the group replacing an instance that fails its health checks, and it does not stop you terminating the instance yourself. A hook never saves a selected instance: completing it with CONTINUE or ABANDON, or letting it time out, all end with a terminating instance terminated (ABANDON also skips any remaining hooks).
Termination policies
The default policy first balances instances across Availability Zones, then (for mixed instances groups) follows the allocation strategy, then prefers instances on the oldest launch template or configuration, then the instance closest to its next billing hour. You can set others in order:
OldestLaunchTemplate: removes instances whose launch template or version is not the current one first, even if those instances were launched recently. This is the one to choose when the goal is to retire instances still running a previous template version.OldestInstance/NewestInstance: by launch time, regardless of template. Oldest helps cycle out long-running instances; newest suits testing a new configuration you may want to remove.ClosestToNextInstanceHour: the instance nearest its next billing hour.AllocationStrategy, and a custom policy backed by a Lambda function, for finer control.
Availability Zone balance always comes first: a policy chooses among instances in the zone the group is reducing.
How long a lifecycle hook can hold an instance
A hook's heartbeat timeout is 30 to 7,200 seconds (default 3,600). When the timeout passes without a response, the hook's default result is applied and the transition continues. For work that takes longer, the instance calls RecordLifecycleActionHeartbeat to restart the timeout, up to a maximum of 48 hours or 100 times the heartbeat timeout, whichever is smaller. When the work ends, it calls CompleteLifecycleAction so the instance does not sit idle for the rest of the timeout. Jobs that can run for longer than that maximum need scale-in protection instead.
Troubleshooting: flapping, stuck at max, and suspended processes
Walk through the classic flapping scenario. A group runs a step policy scaling out when average CPU exceeds 70% and a second policy scaling in below 30%. Load rises and two instances launch. While they boot, their near-idle CPUs drag the group average under 30%, so the scale-in policy terminates instances. Load concentrates on fewer instances, CPU spikes past 70%, and the cycle repeats every few minutes. The fixes: replace both policies with one target tracking policy, which handles scale-out and scale-in together and scales in conservatively; set instance warmup so booting instances stop distorting the average; or, if step policies must stay, widen the gap between the out and in thresholds. Changing the cooldown does not fix it: the cooldown does not apply to step or target tracking policies, and the feedback loop remains.
Alarm in breach, nothing launching. Start with the group's activity history and compare desired with max. The causes fall into three groups:
| What you see | Cause | Fix |
|---|---|---|
| Desired already equals max; no new activities | No headroom | Raise max if the load is legitimate |
| Desired rose, activities show failed launches | Launch failures: InsufficientInstanceCapacity (AWS has no capacity of that type in that zone right now), a vCPU-based instance quota reached, an invalid or deleted AMI, a bad template | For insufficient capacity, diversify: add subnets in more Availability Zones and use a mixed instances policy with several comparable types. For a quota error, request a quota increase. Fix the template or AMI for the others. |
| Desired never changed, no activities at all, alarm in ALARM | A suspended process | Resume it |
Suspended processes. You can suspend individual Auto Scaling processes, usually for maintenance, and forgetting to resume them is a common cause of a group that ignores load. The group can also suspend processes itself after repeated launch failures. Know what each one stops:
AlarmNotification: the group ignores the CloudWatch alarms behind its scaling policies, so target tracking and step policies stop changing desired capacity.ScheduledActions: only scheduled actions stop; alarm-driven policies still work.Launch: the group cannot launch instances, whether for scale-out or replacement.Terminate: the group cannot terminate instances, so scale-in stops.HealthCheck: the group stops marking instances unhealthy.ReplaceUnhealthy: unhealthy instances are not terminated and replaced.AZRebalance: the group stops rebalancing across Availability Zones.AddToLoadBalancer,InstanceRefresh: as named.
Scaling beyond EC2: ECS services and Lambda
The same scaling vocabulary carries to containers, but ECS has two scaling layers and both must work.
| Layer | What scales | Mechanism |
|---|---|---|
| Service auto scaling | The service's desired task count | Application Auto Scaling policies (target tracking on ECSServiceAverageCPUUtilization, ECSServiceAverageMemoryUtilization or ALBRequestCountPerTarget; step; scheduled) |
| Cluster auto scaling (EC2 launch type only) | The container instances that tasks are placed on | An Auto Scaling group capacity provider with managed scaling turned on |
On Fargate there are no instances to manage, so service auto scaling is the whole answer. On EC2-backed clusters, raising the task count only helps if there is room to place tasks; when service events report that no container instance has enough CPU or memory, tasks are waiting for instances. Create an Auto Scaling group capacity provider with managed scaling and update the service to use a capacity provider strategy that includes it (a service that uses a launch type instead of a strategy does not drive managed scaling). ECS then grows the group to fit the tasks waiting to be placed.
Lambda scales the number of concurrent executions automatically with incoming requests, so there is no scaling policy to write. Its controls are about concurrency:
| Control | What it does | Use it for |
|---|---|---|
| Reserved concurrency | Sets aside part of the account's concurrency for one function and caps the function at that number | Guaranteeing a critical function capacity, or limiting one that overwhelms a downstream system |
| Provisioned concurrency | Keeps a number of execution environments initialized in advance | Removing cold-start latency for latency-sensitive traffic; it can itself be scaled on a schedule or by target tracking through Application Auto Scaling |
| Account concurrency quota | The Regional ceiling shared by all functions | Throttling across many functions: request an increase |
Reserved concurrency does not make environments warm, and provisioned concurrency is the only one that removes initialization delay. When invocations are throttled, the function has reached its reserved cap or the account quota; the fix is a concurrency change, not an Auto Scaling group.
Caching for dynamic scalability: CloudFront and ElastiCache
Caching is a scaling mechanism: every request served from a cache is a request your fleet and database never see. CloudFront serves static assets and cacheable dynamic responses (article pages, product pages, API reads) from edge locations, so a higher cache hit ratio shrinks the fleet the Auto Scaling group must keep. For a web tier overloaded by repeated requests for the same content, this is usually cheaper than adding instances; an ElastiCache cluster behind the application relieves the database, not the web tier.
The hit ratio depends on the cache key, which a cache policy defines: the URL plus whichever query strings, headers and cookies you include. Every value you include splits the cache into more variants, so a cache key that includes all query strings and all cookies turns every value that does not affect the response (tracking parameters, session or analytics cookies) into a separate cache entry and drives the hit ratio toward zero. Include only what changes the response. If the origin still needs a value that is not in the cache key, forward it with an origin request policy, which sends values to the origin without adding them to the cache key. TTLs decide how long an object is served before CloudFront checks the origin again; short TTLs mean more origin requests.
CloudFront caches in two layers: edge locations, and regional edge caches behind them. Origin Shield adds a third, central layer in one Region you choose (normally the one closest to your origin): every regional edge cache goes through it, so when many locations ask for the same object at once, such as a popular object whose TTL has just expired, the origin sees one request instead of one per regional cache.
ElastiCache sits between the application and the database. It offers three engines plus a serverless option:
| Option | Replication and failover | Choose it when |
|---|---|---|
| Valkey or Redis OSS (node-based) | Each shard has one primary and up to five replicas; Multi-AZ with automatic failover promotes a replica if the primary fails | The cache must survive node failure, or losing it would overwhelm the database; you need data structures or persistence |
| Memcached (node-based) | None: no replication, no persistence; scale out by adding nodes | A simple, ephemeral object cache where a lost node just means re-reading from the database |
| ElastiCache Serverless (Valkey, Redis OSS or Memcached) | Managed by AWS | Unpredictable or fast-growing traffic and no wish to choose node types, plan shards or manage scaling |
Valkey is the open-source, Redis-compatible engine that ElastiCache now leads with; Redis OSS remains supported. Topology, metrics and scaling for node-based caches follow. For DynamoDB specifically, DAX plays the read-caching role (see the DynamoDB section).
ElastiCache topology, metrics, and scaling
A node-based Valkey or Redis OSS cache is built from shards, and the exam tests what each part scales.
| Change | Scales | Does not scale |
|---|---|---|
| Add read replicas to a shard | Read throughput; availability (failover needs at least one replica) | Write throughput or memory: every replica holds the same data as its primary |
| Move to cluster mode enabled and add shards | Write throughput and total memory: the keyspace is split across several primaries | Availability on its own: each new shard needs its own replicas to fail over |
| Larger node type (vertical) | Memory and CPU of every node | Limited by the largest node you can use |
With cluster mode disabled the cache has a single shard, so writes and memory are limited to one primary node. Multi-AZ with automatic failover requires at least one replica: a cache, or a cluster mode enabled shard, with no replicas has nothing to promote, so a primary failure loses that node's data until it is replaced. Node-based caches with cluster mode enabled also support ElastiCache auto scaling, which adds or removes shards or replicas through target tracking or scheduled policies.
Reading the metrics:
CacheHitRate: the share of reads served from the cache. A falling hit rate sends load back to the database.Evictions: keys removed to make room because memory is full. Rising evictions mean the cache is too small for its working set: add memory (larger nodes or more shards), not replicas.Reclaimed: keys removed because their TTL expired. A hit rate can fall because TTLs are short whileEvictionsstays flat; that is a TTL decision, not a capacity problem.DatabaseMemoryUsagePercentage: how full the memory is; together withEvictions, the signal to add capacity.EngineCPUUtilizationversusCPUUtilization: Valkey and Redis OSS run commands on one main thread, so on a multi-vCPU node the host-wideCPUUtilizationcan look low while the engine thread is saturated. Alarm onEngineCPUUtilizationto catch it.
Scaling RDS and Aurora
RDS scales vertically by modifying the DB instance class. On a Single-AZ instance the change restarts the database, so it causes an outage, either immediately or in the maintenance window. With a Multi-AZ deployment, RDS applies the change to the standby first, fails over to it, then updates the old primary, so the interruption is about the length of a failover (typically one to two minutes) instead of a full resize and restart. The application keeps the same endpoint throughout, because failover repoints the instance's DNS name.
Converting a Single-AZ instance to Multi-AZ needs no downtime: RDS takes a snapshot, builds the standby from it in another Availability Zone and starts synchronous replication, though there can be extra latency while it does so. That makes "convert to Multi-AZ, then resize" a way to change the class with only a brief failover interruption. Compare promoting a read replica: the promoted replica becomes a separate standalone instance with its own endpoint, so applications must be repointed.
Storage autoscaling handles the other vertical axis: when free storage runs low, RDS grows the volume automatically up to a maximum you set. It only grows; storage never shrinks.
For read-heavy load, add read replicas. Replication is asynchronous, so replicas serve eventually consistent reads and the application must send read traffic to them. Alarm on ReplicaLag: rising lag means stale reads now and a longer catch-up if you ever promote the replica. Replicas add read capacity only; they do nothing for writes.
Aurora separates compute from a shared cluster volume that grows automatically. A cluster has one writer and up to 15 Aurora Replicas, all reading the same storage with typically low lag. Aurora Replica auto scaling adds and removes replicas with a target tracking policy on average replica CPU or average connections. It helps reads only, and only the clients that reach the new replicas. Which endpoint the application uses decides that:
| Endpoint | Points to | Picks up auto-scaled replicas? |
|---|---|---|
| Cluster (writer) endpoint | The current writer; follows it after failover | No: use it for writes |
| Reader endpoint | Load-balances connections across the Aurora Replicas | Yes |
| Instance endpoint | One specific instance | No: connections stay pinned to that instance |
| Custom endpoint with a static member list | Only the instances listed | No: new replicas are not added |
| Custom endpoint with an exclusion list | Every instance except those excluded | Yes |
Traffic sent to individual instance endpoints or a static member list never reaches replicas added later, so auto scaling adds capacity nobody uses; the reader endpoint (or an exclusion-list custom endpoint) spreads reads across new replicas automatically. Aurora Serverless v2 scales an instance's capacity continuously in ACUs (Aurora capacity units) between a minimum and maximum you set, which suits spiky or unpredictable database load that a fixed instance class handles badly.
Scaling DynamoDB: capacity modes and throttling
DynamoDB scales through its two capacity modes.
| On-demand | Provisioned (with auto scaling) | |
|---|---|---|
| Billing | Per request | Per provisioned capacity unit per hour |
| How it scales | Instantly handles up to double the table's previous peak traffic; beyond that it adapts, so a jump of more than double within about 30 minutes can still throttle. Warm throughput can be raised in advance for a known launch or event. | Application Auto Scaling target tracking on consumed capacity: you set a target utilization, a minimum and a maximum. It reacts to CloudWatch metrics over several minutes, so it cannot follow an instant spike. |
| Best for | Spiky, unpredictable or new workloads | Steady, predictable traffic, where it costs less |
| Reserved capacity | Not available | Available, for a further discount on steady use |
Throttling tells you the mode or its limits are wrong. Requests above provisioned throughput fail with ProvisionedThroughputExceededException, visible in the ThrottledRequests and read/write throttle-event metrics. A steady workload that throttles needs more capacity (or a higher auto scaling maximum). A bursty workload that throttles between auto scaling adjustments needs on-demand mode: raising the auto scaling maximum or shortening its cooldowns does not make it react faster, because it still waits for the metrics to show the load. Throttling while the table has plenty of unused capacity points to a hot partition: one partition key taking a disproportionate share of traffic. Adaptive capacity softens this automatically, but the durable fix is a higher-cardinality partition key.
For hot reads, front the table with DynamoDB Accelerator (DAX), an in-memory cache that is API-compatible with DynamoDB. The application swaps in the DAX client and keeps making the same calls, and gets microsecond reads for eventually consistent requests. ElastiCache can also cache DynamoDB data, but then the application must contain the caching logic (check the cache, read the table on a miss, write the result back, invalidate on change).
Tip. Task 2.1 questions hand you a demand pattern or a misbehaving fleet and ask for the best-fit control, often setting near-twins against each other: target tracking versus step versus predictive scaling, instance warmup versus the default cooldown, grace period versus target group threshold, scale-in protection versus a termination hook, AlarmNotification versus ScheduledActions, reserved versus provisioned concurrency. Expect arithmetic on target values (requests per target, backlog per instance) and metric reading: Evictions versus Reclaimed, EngineCPUUtilization versus CPUUtilization, ReplicaLag, throttle events. Database stems hinge on endpoints and modes: the reader endpoint for auto-scaled Aurora Replicas, a same-endpoint Multi-AZ resize versus a new-endpoint replica promotion, on-demand versus provisioned DynamoDB. Watch for answers that add availability (Multi-AZ, replicas) when the question asks for write capacity or memory, and read whether the goal is more capacity or more resilience before choosing.
- "Keep a metric near a value" → target tracking, on a metric that falls as capacity is added: average CPU, ALBRequestCountPerTarget (not total RequestCount), or SQS backlog per instance.
- Backlog per instance target = acceptable wait ÷ processing time per message, a number of messages (120 s ÷ 4 s = 30).
- The default cooldown applies only to simple scaling; target tracking and step scaling use instance warmup, which keeps booting instances out of the aggregated metric.
- To pre-warm for a known peak, have the scheduled action raise min capacity (and lower it later); raising only desired is undone by target tracking.
- Predictive scaling needs recurring history; start in forecast only mode, and use a scheduling buffer for slow-booting instances.
- Scale-in protection keeps an instance from being selected; a termination hook only delays an instance already selected; OldestLaunchTemplate removes instances on an old template version first.
- Alarm in ALARM with no activities → check suspended processes (AlarmNotification); InsufficientInstanceCapacity → more Availability Zones and a mixed instances policy, not a quota increase.
- ECS on EC2 needs both service auto scaling (tasks) and an ASG capacity provider with managed scaling (instances); Lambda cold starts → provisioned concurrency, not reserved.
- CloudFront: keep the cache key to what changes the response; Origin Shield centralizes origin requests. ElastiCache: Evictions = memory pressure, Reclaimed = expired TTLs; replicas add reads, shards add writes and memory.
- Multi-AZ RDS resizes with a brief failover on the same endpoint; Aurora Replica auto scaling only helps clients on the reader endpoint; DynamoDB on-demand absorbs up to double the previous peak, and DAX adds microsecond reads without caching code.
Frequently asked questions
What is the difference between target tracking and step scaling?
Target tracking holds a metric at a value you choose, such as average CPU at 50%, and AWS creates and manages the CloudWatch alarms and scales in both directions. Step scaling uses alarms you create plus step adjustments sized to how far the metric breached, and it can keep responding while a scaling activity is in progress. Use target tracking by default; use step scaling when you need different-sized responses at different severity levels.
Why does my Auto Scaling group keep launching and terminating instances repeatedly?
That is flapping. It usually comes from paired scale-out and scale-in policies with thresholds too close together, combined with booting instances dragging the average metric down so the scale-in policy fires. Fix it by replacing the pair with one target tracking policy, setting the group's default instance warmup to the time an instance takes to start serving, or widening the gap between the thresholds. Changing the default cooldown does not help, because it applies only to simple scaling policies.
What is the difference between scale-in protection and a termination lifecycle hook?
Scale-in protection removes an instance from selection when an Auto Scaling group scales in, so a busy instance is never chosen. A termination lifecycle hook acts after selection: it holds the chosen instance in Terminating:Wait for up to its heartbeat timeout (30 to 7,200 seconds, extendable with heartbeats to 48 hours or 100 times the timeout, whichever is smaller), and the instance still terminates afterwards. Use protection for long-running work and a hook for draining or cleanup.
How do I scale SQS worker instances with target tracking?
Track backlog per instance rather than queue length. Build a metric math expression that divides the queue's ApproximateNumberOfMessagesVisible by the Auto Scaling group's GroupInServiceInstances, and set the target to the acceptable wait time divided by the average processing time per message. If messages may wait 120 seconds and each takes 4 seconds, the target is 30 messages per instance.
Does changing an RDS instance class cause downtime?
On a Single-AZ instance, yes: the database restarts while the change applies, immediately or in the maintenance window. In a Multi-AZ deployment, RDS changes the standby first and fails over to it, so the interruption is about the length of a failover (typically one to two minutes) and the endpoint stays the same. Converting a Single-AZ instance to Multi-AZ needs no downtime, so it can be done before the resize.
What is the difference between Evictions and Reclaimed in ElastiCache?
Evictions counts keys removed because the cache ran out of memory, so rising evictions mean the cache is too small for its working set and needs more memory (larger nodes or more shards). Reclaimed counts keys removed because their TTL expired. A falling cache hit rate with flat Evictions points to TTLs, not capacity. Adding read replicas does not add memory, because each replica holds the same data as its primary.
When should I use DynamoDB on-demand mode instead of provisioned capacity?
Use on-demand for spiky, unpredictable or new workloads: it instantly handles up to double the table's previous peak, and warm throughput can be raised ahead of a known event. Use provisioned capacity with auto scaling for steady, predictable traffic, where it costs less and reserved capacity can cut cost further (reserved capacity applies only to provisioned mode). If a provisioned table throttles during sudden spikes, raising the auto scaling maximum will not make it react faster; switch to on-demand.
Should I use Valkey, Redis OSS or Memcached for ElastiCache?
Choose Valkey or Redis OSS when the cache must survive node failure: each shard can have up to five replicas, and Multi-AZ with automatic failover promotes one if the primary fails (it needs at least one replica). They also offer data structures and persistence. Choose Memcached for a simple, ephemeral object cache that scales by adding nodes but has no replication. For unpredictable traffic without capacity planning, ElastiCache Serverless runs any of the three engines.
Source
This lesson covers the "Reliability and Business Continuity" domain of the official SOA-C03 exam guide. Vendors revise their guides — check the source for the current version.
- AWS Certified CloudOps Engineer – Associate (SOA-C03) exam guide — Amazon Web Services
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.