# CloudWatch Metric, Composite, and Anomaly Detection Alarms: Key Differences and Implementation Guide

> Understand CloudWatch metric, composite, and anomaly detection alarms. Learn their differences and how to implement them for effective AWS monitoring. Get the key distinctions now.

- Repository: [Amazon Web Services/agent-toolkit-for-aws](https://github.com/aws/agent-toolkit-for-aws)
- Tags: deep-dive
- Published: 2026-07-03

---

**CloudWatch metric alarms trigger on static thresholds, composite alarms aggregate multiple alarm states using Boolean logic (AND/OR/NOT), and anomaly detection alarms use machine learning to detect statistical deviations from historical baselines.**

Amazon CloudWatch provides three distinct alarm types for infrastructure monitoring, each designed for specific operational patterns. According to the AWS Agent Toolkit for AWS repository, understanding the architectural differences between standard metric alarms, composite alarms, and anomaly detection alarms is critical for designing effective observability strategies, as documented in the [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) and [`skills/core-skills/aws-observability/references/metrics.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/metrics.md) files.

## Standard Metric Alarms: Static Threshold Monitoring

**Standard metric alarms** represent the baseline CloudWatch alarm type. They monitor individual metrics against static thresholds and support the full range of CloudWatch actions, including EC2 lifecycle operations (stop, terminate, reboot, recover) and Auto Scaling actions. These alarms evaluate raw metric data over specified periods and transition between `OK`, `ALARM`, and `INSUFFICIENT_DATA` states based on user-defined thresholds.

## Composite Alarms: Boolean Logic for Alert Aggregation

**Composite alarms** aggregate the states of other alarms rather than monitoring raw metrics directly. They evaluate Boolean expressions to reduce alert fatigue or express service-level health.

### Underlying Data and Evaluation Mechanics

Composite alarms rely on the **state** (`OK`, `ALARM`, or `INSUFFICIENT_DATA`) of existing metric alarms. As implemented in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 22-27), the composite alarm evaluates whenever any underlying alarm changes state, using the same evaluation period as the underlying alarms without additional data windows.

### Limits and Constraints

The repository defines strict limits for composite alarms in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 34-36):

- **≤ 100 underlying alarms** per composite alarm
- **≤ 150 composite alarms** per underlying alarm
- **≤ 500 rule elements** total

### Action Limitations

Composite alarms **cannot** trigger EC2-related actions (stop, terminate, reboot, recover) or Auto Scaling actions. They support SNS, Lambda, and SSM actions, and uniquely support the `ActionsSuppressor` pattern for maintenance windows. This restriction is documented in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 28-34).

### Cross-Account Restrictions

All underlying alarms must reside in the **same account and region** as the composite alarm. While monitoring accounts can observe source-account alarms via Observability Access Manager (OAM), they cannot serve as sources for composite alarms according to [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 35-38).

## Anomaly Detection Alarms: Statistical Deviation Monitoring

**Anomaly detection alarms** use the `ANOMALY_DETECTION_BAND` function to identify outliers in metrics with seasonal or variable patterns where static thresholds would cause false positives.

### Underlying Data and Evaluation

These alarms work on a **single metric** (or metric-math expression) and internally compute a dynamic threshold band. The anomaly detector trains on up to **2 weeks of historical data** before evaluating each datapoint against the band. Evaluation periods typically default to `1` because the band already models variance, as noted in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 22-27).

### Metric-Math Restrictions

The [`skills/core-skills/aws-observability/references/metrics.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/metrics.md) file (lines 94-98) specifies several constraints:

- Only **one** `ANOMALY_DETECTION_BAND` per expression
- Cannot combine with `METRICS()` or `SEARCH` functions
- Cannot use high-resolution metrics

### Cost Considerations

Anomaly detection alarms incur slightly higher costs than standard metric alarms due to additional `GetMetricData` API calls for `ANOMALY_DETECTION_BAND` usage, as mentioned in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 26-28).

## Implementation Examples

### Creating a Composite Alarm (AWS CLI)

First, create the underlying metric alarms:

```bash
aws cloudwatch put-metric-alarm \
  --alarm-name HighCPU \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
  --threshold 80 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 --datapoints-to-alarm 2 \
  --period 60 --statistic Average \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:OpsAlerts

aws cloudwatch put-metric-alarm \
  --alarm-name HighErrorRate \
  --metric-name Errors \
  --namespace AWS/Lambda \
  --dimensions Name=FunctionName,Value=my-function \
  --threshold 5 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 3 --datapoints-to-alarm 2 \
  --period 60 --statistic Sum \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:OpsAlerts

```

Then create the composite alarm using `put-composite-alarm`, which wraps `put-metric-alarm` with the `AlarmRule` parameter:

```bash
aws cloudwatch put-composite-alarm \
  --alarm-name ServiceHealth \
  --alarm-rule "ALARM('HighCPU') AND ALARM('HighErrorRate')" \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:OpsAlerts

```

This syntax is documented in [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 35-40).

### Creating an Anomaly Detection Alarm (CloudFormation)

```yaml
Resources:
  AnomalyDetector:
    Type: AWS::CloudWatch::AnomalyDetector
    Properties:
      MetricName: Invocations
      Namespace: AWS/Lambda
      Stat: Sum

  AnomalyAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      ComparisonOperator: LessThanLowerOrGreaterThanUpperThreshold
      EvaluationPeriods: 1
      Metrics:
        - Expression: ANOMALY_DETECTION_BAND(m1, 2)
          Id: ad1
        - Id: m1
          MetricStat:
            Metric:
              MetricName: Invocations
              Namespace: AWS/Lambda
            Period: 86400
            Stat: Sum
      ThresholdMetricId: ad1
      TreatMissingData: breaching
      AlarmActions:
        - arn:aws:sns:us-east-1:123456789012:OpsAlerts

```

This configuration references [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 49-66).

### Provisioning with AWS CDK

**Composite Alarm:**

```typescript
import { CompositeAlarm, AlarmRule, AlarmState } from 'aws-cdk-lib/aws-cloudwatch';

const composite = new CompositeAlarm(this, 'ServiceHealth', {
  alarmRule: AlarmRule.anyOf(
    AlarmRule.fromAlarm(highCpuAlarm, AlarmState.ALARM),
    AlarmRule.fromAlarm(highErrorAlarm, AlarmState.ALARM)
  ),
});

```

**Anomaly Detection Alarm:**

```typescript
import { Alarm, ComparisonOperator, MathExpression } from 'aws-cdk-lib/aws-cloudwatch';
import { Duration } from 'aws-cdk-lib';

const invocations = metric.metricInvocations({ period: Duration.minutes(5) });

const anomalyAlarm = new Alarm(this, 'InvocationsAnomaly', {
  metric: new MathExpression({
    expression: 'ANOMALY_DETECTION_BAND(m1, 2)',
    usingMetrics: { m1: invocations },
    label: 'Invocations Anomaly',
  }),
  comparisonOperator: ComparisonOperator.LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD,
  evaluationPeriods: 1,
  alarmActions: [snsTopic],
});

```

Both CDK examples are derived from [`skills/core-skills/aws-observability/references/alarms.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/alarms.md) (lines 35-41 and 49-58).

## Summary

- **Standard metric alarms** monitor static thresholds on individual metrics and support all CloudWatch actions, including EC2 lifecycle operations.
- **Composite alarms** aggregate alarm states using Boolean logic, support up to 100 underlying alarms and 500 rule elements, and cannot trigger EC2 or Auto Scaling actions, but support action suppression via `ActionsSuppressor`.
- **Anomaly detection alarms** use `ANOMALY_DETECTION_BAND` to detect statistical outliers, cannot combine with `METRICS()` or `SEARCH` functions, and cannot use high-resolution metrics.
- Composite alarms require all underlying alarms to be in the same account and region, while anomaly detection alarms follow standard cross-account metric permissions.
- Neither composite nor anomaly detection alarms support EC2 stop, terminate, reboot, or recover actions.

## Frequently Asked Questions

### Can composite alarms reference anomaly detection alarms?

Yes, composite alarms can reference any metric alarm, including those using anomaly detection bands. The composite alarm monitors the state (`OK` or `ALARM`) of the underlying anomaly detection alarm, not the raw metric values. Both alarms must reside in the same AWS account and region.

### Why can't I use high-resolution metrics with anomaly detection?

High-resolution metrics (sub-minute granularity) are incompatible with the `ANOMALY_DETECTION_BAND` function because the machine learning algorithm requires consistent historical training data. According to [`skills/core-skills/aws-observability/references/metrics.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-observability/references/metrics.md) (lines 94-98), this restriction ensures the statistical model maintains accuracy across the 2-week training window.

### Which alarm type is best for reducing alert fatigue during deployments?

**Composite alarms** provide the best mechanism for suppressing alerts during maintenance windows. By specifying an `ActionsSuppressor` alarm in your composite configuration, you can prevent notifications when the suppressor alarm is in `ALARM` state. This pattern is not available with standard metric or anomaly detection alarms.

### Do composite alarms incur additional CloudWatch costs?

Composite alarms are billed as standard alarms through the `PutMetricAlarm` API, plus the cost of all underlying alarms. Unlike anomaly detection alarms—which generate additional `GetMetricData` API calls for band calculations—composite alarms only evaluate state changes without additional metric retrieval costs.