or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdscalable-targets.mdscheduled-scaling.mdstep-scaling.mdtarget-tracking.md
tile.json

target-tracking.mddocs/

Target Tracking Scaling

Target tracking scaling policies automatically adjust capacity to maintain a target metric value. This scaling type is ideal for maintaining utilization levels and works with both predefined AWS metrics and custom CloudWatch metrics.

Capabilities

TargetTrackingScalingPolicy Class

Creates and manages target tracking scaling policies that automatically scale resources to maintain a target metric value.

/**
 * Define a target tracking scaling policy
 * Automatically scales resources to maintain a target metric value
 */
class TargetTrackingScalingPolicy extends Construct {
  /**
   * Create a new TargetTrackingScalingPolicy
   * @param scope - CDK construct scope
   * @param id - Construct identifier
   * @param props - Target tracking scaling policy properties
   */
  constructor(scope: Construct, id: string, props: TargetTrackingScalingPolicyProps);
  
  /**
   * ARN of the scaling policy
   */
  readonly scalingPolicyArn: string;
}

/**
 * Base interface for target tracking props
 * Contains attributes common to target tracking policies
 */
interface BaseTargetTrackingProps {
  /**
   * A name for the scaling policy
   * @default Automatically generated name
   */
  readonly policyName?: string;
  
  /**
   * Indicates whether scale in by the target tracking policy is disabled
   * If true, scale in is disabled and the policy won't remove capacity
   * @default false
   */
  readonly disableScaleIn?: boolean;
  
  /**
   * Period after a scale in activity completes before another scale in activity can start
   * @default Duration.seconds(300) for ECS, Spot Fleet, EMR, AppStream, Aurora, SageMaker, Custom resources
   * @default Duration.seconds(0) for DynamoDB, Comprehend, Lambda
   */
  readonly scaleInCooldown?: cdk.Duration;
  
  /**
   * Period after a scale out activity completes before another scale out activity can start
   * @default Duration.seconds(300) for ECS, Spot Fleet, EMR, AppStream, Aurora, SageMaker, Custom resources
   * @default Duration.seconds(0) for DynamoDB, Comprehend, Lambda
   */
  readonly scaleOutCooldown?: cdk.Duration;
}

/**
 * Properties for a Target Tracking policy that include the metric but exclude the target
 */
interface BasicTargetTrackingScalingPolicyProps extends BaseTargetTrackingProps {
  /**
   * The target value for the metric
   */
  readonly targetValue: number;
  
  /**
   * A predefined metric for application autoscaling
   * The metric must track utilization. Scaling out happens if metric > target value,
   * scaling in happens if metric < target value.
   * Exactly one of customMetric or predefinedMetric must be specified.
   * @default No predefined metrics
   */
  readonly predefinedMetric?: PredefinedMetric;
  
  /**
   * Identify the resource associated with the metric type
   * Only used for predefined metric ALBRequestCountPerTarget
   * Example: app/<load-balancer-name>/<load-balancer-id>/targetgroup/<target-group-name>/<target-group-id>
   * @default No resource label
   */
  readonly resourceLabel?: string;
  
  /**
   * A custom metric for application autoscaling
   * The metric must track utilization. Scaling out happens if metric > target value,
   * scaling in happens if metric < target value.
   * Exactly one of customMetric or predefinedMetric must be specified.
   * @default No custom metric
   */
  readonly customMetric?: cloudwatch.IMetric;
}

/**
 * Properties for a concrete TargetTrackingPolicy
 * Adds the scalingTarget
 */
interface TargetTrackingScalingPolicyProps extends BasicTargetTrackingScalingPolicyProps {
  /**
   * The scalable target
   */
  readonly scalingTarget: IScalableTarget;
}

Usage Examples:

import * as appscaling from '@aws-cdk/aws-applicationautoscaling';
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';

// Using predefined metrics
target.scaleToTrackMetric('CPUTracking', {
  targetValue: 70,
  predefinedMetric: appscaling.PredefinedMetric.ECS_SERVICE_AVERAGE_CPU_UTILIZATION,
  scaleOutCooldown: cdk.Duration.minutes(5),
  scaleInCooldown: cdk.Duration.minutes(10),
});

// Lambda provisioned concurrency tracking
lambdaTarget.scaleToTrackMetric('ConcurrencyTracking', {
  targetValue: 0.7,
  predefinedMetric: appscaling.PredefinedMetric.LAMBDA_PROVISIONED_CONCURRENCY_UTILIZATION,
  disableScaleIn: false,
});

// Using custom metrics
const customMetric = new cloudwatch.Metric({
  namespace: 'MyApp/Performance',
  metricName: 'RequestsPerInstance',
  dimensionsMap: {
    ServiceName: 'my-service',
  },
  statistic: 'Average',
});

target.scaleToTrackMetric('CustomMetricTracking', {
  targetValue: 100,
  customMetric: customMetric,
  scaleOutCooldown: cdk.Duration.minutes(3),
});

// DynamoDB read capacity tracking
dynamoTarget.scaleToTrackMetric('ReadCapacityTracking', {
  targetValue: 70,
  predefinedMetric: appscaling.PredefinedMetric.DYNAMODB_READ_CAPACITY_UTILIZATION,
});

Predefined Metrics

AWS provides predefined metrics for common scaling scenarios across different services.

/**
 * One of the predefined autoscaling metrics
 */
enum PredefinedMetric {
  /**
   * Average percentage of instances in an AppStream fleet that are being used
   */
  APPSTREAM_AVERAGE_CAPACITY_UTILIZATION = 'AppStreamAverageCapacityUtilization',
  
  /**
   * Percentage of provisioned read capacity units utilized by a Keyspaces table
   */
  CASSANDRA_READ_CAPACITY_UTILIZATION = 'CassandraReadCapacityUtilization',
  
  /**
   * Percentage of provisioned write capacity units utilized by a Keyspaces table
   */
  CASSANDRA_WRITE_CAPACITY_UTILIZATION = 'CassandraWriteCapacityUtilization',
  
  /**
   * Percentage of provisioned inference units utilized by a Comprehend endpoint
   */
  COMPREHEND_INFERENCE_UTILIZATION = 'ComprehendInferenceUtilization',
  
  /**
   * Average CPU Utilization of read replica instances in a Neptune DB cluster
   */
  NEPTURE_READER_AVERAGE_CPU_UTILIZATION = 'NeptuneReaderAverageCPUUtilization',
  
  /**
   * Percentage of provisioned read capacity units consumed by a DynamoDB table
   */
  DYNAMODB_READ_CAPACITY_UTILIZATION = 'DynamoDBReadCapacityUtilization',
  
  /**
   * Percentage of provisioned write capacity units consumed by a DynamoDB table
   * Note: Due to a jsii bug, the actual implementation uses a dummy suffix internally 
   * but will be replaced with the correct value when used
   */
  DYNAMODB_WRITE_CAPACITY_UTILIZATION = 'DynamoDBWriteCapacityUtilization',
  
  /**
   * DYANMODB_WRITE_CAPACITY_UTILIZATION
   * @deprecated use PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION
   */
  DYANMODB_WRITE_CAPACITY_UTILIZATION = 'DynamoDBWriteCapacityUtilization',
  
  /**
   * ALB_REQUEST_COUNT_PER_TARGET
   */
  ALB_REQUEST_COUNT_PER_TARGET = 'ALBRequestCountPerTarget',
  
  /**
   * RDS_READER_AVERAGE_CPU_UTILIZATION
   */
  RDS_READER_AVERAGE_CPU_UTILIZATION = 'RDSReaderAverageCPUUtilization',
  
  /**
   * RDS_READER_AVERAGE_DATABASE_CONNECTIONS
   */
  RDS_READER_AVERAGE_DATABASE_CONNECTIONS = 'RDSReaderAverageDatabaseConnections',
  
  /**
   * EC2_SPOT_FLEET_REQUEST_AVERAGE_CPU_UTILIZATION
   */
  EC2_SPOT_FLEET_REQUEST_AVERAGE_CPU_UTILIZATION = 'EC2SpotFleetRequestAverageCPUUtilization',
  
  /**
   * EC2_SPOT_FLEET_REQUEST_AVERAGE_NETWORK_IN
   */
  EC2_SPOT_FLEET_REQUEST_AVERAGE_NETWORK_IN = 'EC2SpotFleetRequestAverageNetworkIn',
  
  /**
   * EC2_SPOT_FLEET_REQUEST_AVERAGE_NETWORK_OUT
   */
  EC2_SPOT_FLEET_REQUEST_AVERAGE_NETWORK_OUT = 'EC2SpotFleetRequestAverageNetworkOut',
  
  /**
   * SAGEMAKER_VARIANT_INVOCATIONS_PER_INSTANCE
   */
  SAGEMAKER_VARIANT_INVOCATIONS_PER_INSTANCE = 'SageMakerVariantInvocationsPerInstance',
  
  /**
   * ECS_SERVICE_AVERAGE_CPU_UTILIZATION
   */
  ECS_SERVICE_AVERAGE_CPU_UTILIZATION = 'ECSServiceAverageCPUUtilization',
  
  /**
   * ECS_SERVICE_AVERAGE_MEMORY_UTILIZATION
   */
  ECS_SERVICE_AVERAGE_MEMORY_UTILIZATION = 'ECSServiceAverageMemoryUtilization',
  
  /**
   * LAMBDA_PROVISIONED_CONCURRENCY_UTILIZATION
   */
  LAMBDA_PROVISIONED_CONCURRENCY_UTILIZATION = 'LambdaProvisionedConcurrencyUtilization',
  
  /**
   * KAFKA_BROKER_STORAGE_UTILIZATION
   */
  KAFKA_BROKER_STORAGE_UTILIZATION = 'KafkaBrokerStorageUtilization',
  
  /**
   * ELASTIC_CACHE_PRIMARY_ENGINE_CPU_UTILIZATION
   */
  ELASTICACHE_PRIMARY_ENGINE_CPU_UTILIZATION = 'ElastiCachePrimaryEngineCPUUtilization',
  
  /**
   * ELASTIC_CACHE_REPLICA_ENGINE_CPU_UTILIZATION
   */
  ELASTICACHE_REPLICA_ENGINE_CPU_UTILIZATION = 'ElastiCacheReplicaEngineCPUUtilization',
  
  /**
   * ELASTIC_CACHE_DATABASE_MEMORY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE
   */
  ELASTICACHE_DATABASE_MEMORY_USAGE_COUNTED_FOR_EVICT_PERCENTAGE = 'ElastiCacheDatabaseMemoryUsageCountedForEvictPercentage',
}

Custom Metrics

For custom metrics, you can use CloudWatch metrics with specific requirements.

Requirements for Custom Metrics:

  • Must be a direct metric (not a math expression)
  • Supported statistics: Average, Minimum, Maximum, SampleCount, Sum
  • Cannot use percentile statistics (p50, p90, etc.)
  • Must track utilization where higher values indicate need to scale out

Example:

// Custom metric example
const requestLatency = new cloudwatch.Metric({
  namespace: 'MyApp/Performance',
  metricName: 'AverageResponseTime',
  dimensionsMap: {
    ServiceName: 'api-service',
  },
  statistic: 'Average',
  period: cdk.Duration.minutes(5),
});

// Use with target tracking (scale out when latency > 200ms)
target.scaleToTrackMetric('LatencyTracking', {
  targetValue: 200,
  customMetric: requestLatency,
  scaleOutCooldown: cdk.Duration.minutes(2),
  scaleInCooldown: cdk.Duration.minutes(5),
});