Application Auto Scaling
AWS Application Auto Scaling — scalable targets, step / target-tracking / predictive policies, scheduled actions, scaling activities, predictive forecasts, tags. JSON 1.1 protocol.
fakecloud implements AWS Application Auto Scaling's full JSON 1.1 control plane: 14 operations covering scalable targets, scaling policies, scheduled actions, scaling activities, predictive forecasts, and tags. 100% Smithy conformance.
Status: 100% control-plane coverage.
Supported today
- Scalable targets —
RegisterScalableTargetacceptsServiceNamespace,ResourceId,ScalableDimension,MinCapacity,MaxCapacity,RoleARN,SuspendedState. Re-registering an existing target only patches the supplied fields (PUT-merge).RoleARNdefaults to the per-namespace service-linked role ARN (e.g.AWSServiceRoleForApplicationAutoScaling_ECSService).DescribeScalableTargetsfilters byServiceNamespace+ResourceIds+ScalableDimensionwithMaxResults+NextTokenpagination.DeregisterScalableTargetcascades: anyScalingPolicyorScheduledActionfor the same target is removed, so test state stays consistent. Supported namespaces includeecs,lambda,dynamodb,rds,elasticache,sagemaker,elasticmapreduce,appstream,cassandra,kafka,neptune,ec2,comprehend. - Scaling policies —
PutScalingPolicyacceptsPolicyName+PolicyType(StepScaling/TargetTrackingScaling/PredictiveScaling) and stores the corresponding configuration verbatim (round-tripped throughDescribeScalingPolicies). Returns a deterministicPolicyARNand an emptyAlarmslist. Without a registered scalable target, returnsObjectNotFoundException.DescribeScalingPoliciesfilters byPolicyNames/ResourceId/ScalableDimensionand paginates.DeleteScalingPolicyremoves by name + target tuple. - Scheduled actions —
PutScheduledActionacceptsSchedule(at(...)/rate(...)/cron(...)),Timezone,StartTime,EndTime,ScalableTargetAction(MinCapacity/MaxCapacity). Existing actions PUT-merge supplied fields.DescribeScheduledActionspaginates, filters by names + target.DeleteScheduledActionremoves by name + target tuple. Targets must already be registered. - Scaling activities —
DescribeScalingActivitiesreturns the per-target activity log newest-first withIncludeNotScaledActivitiesfiltering (default suppressesFailed). - Predictive scaling forecast —
GetPredictiveScalingForecastrequires the policy to bePolicyType = PredictiveScaling(otherwiseValidationException), then returns deterministic hourly Load + Capacity buckets betweenStartTimeandEndTimecapped at one week. Values are computed from the hour-of-day so tests can assert specific points. - Tags —
TagResourceupserts tag pairs keyed byResourceARN,UntagResourceremoves byTagKeys,ListTagsForResourcereturns the current tag map. Unknown ARNs returnObjectNotFoundException.
Smoke test
fakecloud &
aws --endpoint-url http://localhost:4566 application-autoscaling register-scalable-target \
--service-namespace ecs \
--resource-id service/cluster/api \
--scalable-dimension ecs:service:DesiredCount \
--min-capacity 1 --max-capacity 10
aws --endpoint-url http://localhost:4566 application-autoscaling put-scaling-policy \
--service-namespace ecs \
--resource-id service/cluster/api \
--scalable-dimension ecs:service:DesiredCount \
--policy-name scale-out \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 70.0,
"PredefinedMetricSpecification": {"PredefinedMetricType": "ECSServiceAverageCPUUtilization"}
}'
aws --endpoint-url http://localhost:4566 application-autoscaling describe-scaling-policies \
--service-namespace ecsReal scaling apply hooks
The Application Auto Scaling watcher actually resizes the underlying resource when scaling policies fire. Today the watcher mutates:
- DynamoDB — provisioned
ReadCapacityUnitsandWriteCapacityUnitson tables (and Global Secondary Indexes) registered as scalable targets. - ECS — service
DesiredCountforecs:service:DesiredCounttargets. When a target-tracking or step policy fires for an ECS service, the watcher calls the ECS capacity hook, which updates the service'sDesiredCountand walks the running task set so the new bound is reflected inDescribeServicesand the underlying Docker task count. Step scaling andTargetTrackingScalingagainstECSServiceAverageCPUUtilization/ECSServiceAverageMemoryUtilizationboth apply.
The watcher ticks every 15 seconds, walks every registered scalable target, and applies one of two algorithms per policy:
TargetTrackingScaling— reads the latest sample of thePredefinedMetricSpecification.PredefinedMetricTypemetric from CloudWatch (DynamoDBReadCapacityUtilization/DynamoDBWriteCapacityUtilization, dimensioned byTableName), computesdesired = current * (utilisation / TargetValue), clamps to[MinCapacity, MaxCapacity], and rounds up before calling the DynamoDB capacity hook. HonoursScaleInCooldown/ScaleOutCooldown.StepScalingScaling— fires whenever a CloudWatch alarm whoseAlarmActionscontains the policy ARN transitions toALARM. The first matchingStepAdjustmentis applied via the configuredAdjustmentType(ChangeInCapacity,ExactCapacity,PercentChangeInCapacitywith optionalMinAdjustmentMagnitude). HonoursCooldown.
Each decision lands as a ScalingActivity row so DescribeScalingActivities shows the real history. Unsuccessful attempts (cooldown, missing table, billing-mode mismatch) record a Failed activity with a NotScaledReason.
To deterministically force the watcher off the wall-clock interval — useful in tests — POST /_fakecloud/application-autoscaling/tick. The response shape is { "applied": <int> }. The introspection SDKs expose this as fakecloud.applicationAutoscaling.tick().
Scheduled actions
PutScheduledAction registers a one-shot or recurring capacity change. fakecloud's executor evaluates every scheduled action every 30 seconds and fires the ones whose Schedule expression is currently due:
at(yyyy-mm-ddThh:mm:ss)— fires once when wall-clock catches up.cron(min hour dom month dow year)— recurring, evaluated against the action'sTimezone(IANA name; falls back to UTC when missing or unrecognized). The supported grammar matches EventBridge Scheduler — wildcards (*/?) and single numeric values per field. Ranges, lists, and step values silently never fire so a malformed expression doesn't blow up the executor.
When an action fires the executor mutates the linked ScalableTarget to the action's ScalableTargetAction.{MinCapacity, MaxCapacity} and, for DynamoDB targets, calls the same capacity hook used by target-tracking / step scaling so the table's provisioned throughput moves into the new bounds. Each fire appends a ScalingActivity row whose Cause references the scheduled action by name and schedule. Per-minute dedupe (via last_fired_at) prevents a cron(* * * * ? *) schedule from re-firing inside the same wall-clock minute.
To deterministically fire scheduled actions in tests — without waiting on the 30s interval — POST /_fakecloud/application-autoscaling/scheduled-tick. Response shape is { "fired": <int> }. The introspection SDKs expose this as fakecloud.applicationAutoscaling.scheduledTick().
Caveats
DynamoDB and ECS are the namespaces with real apply hooks today. Lambda provisioned concurrency, RDS Aurora capacity, ElastiCache replicas, and the rest of Application Auto Scaling's service namespaces still store policy and scheduled-action configurations verbatim — the bound updates land on the ScalableTarget but no per-namespace apply hook is wired yet, so the underlying resource isn't resized. Predictive forecasts are deterministic synthetic curves, not actual ML predictions. CloudWatch alarms reported under ScalingPolicy.Alarms remain empty — the watcher resolves alarms by walking CloudWatch state directly rather than mirroring AWS's auto-attach behaviour.