> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Route AWS CloudWatch alarms into Rootly via SNS

> Receive alerts from AWS CloudWatch in Rootly to trigger incidents, route notifications to on-call teams, and automatically resolve alerts when alarms recover.

## Overview

The AWS CloudWatch integration allows Rootly to treat CloudWatch alarms as a native alert source. The integration uses Amazon Simple Notification Service (SNS) to deliver CloudWatch alarm state change events to Rootly via HTTPS webhooks.

When a CloudWatch alarm transitions into the `ALARM` state, Rootly creates a new alert or updates an existing unresolved alert. When the same alarm transitions back into the `OK` state, Rootly automatically resolves the corresponding alert. This behavior enables CloudWatch alarms to participate fully in Rootly’s alert routing, on-call, and incident management workflows.

Alerts created from CloudWatch can be routed to services, escalation policies, or teams, and customized using alert templates that parse fields from the SNS payload.

<Callout icon="repeat" color="#DBEAFE">
  CloudWatch alerts are stateful. Rootly creates alerts when alarms enter the ALARM state and resolves them automatically when the same alarms return to OK.
</Callout>

## How the Integration Works

CloudWatch alarms publish state change notifications to an SNS topic. Rootly subscribes to this SNS topic using an HTTPS webhook endpoint generated when you create a CloudWatch alert source in Rootly.

Each SNS notification contains information about the alarm, including its name, ARN, state, reason for the state change, and timestamp. Rootly uses the alarm ARN as the external identifier for the alert, ensuring that repeated alarm triggers update the same alert and that alerts are resolved when the alarm returns to an OK state.

## Prerequisites

Before configuring the integration, ensure that you have access to an AWS account with permissions to manage CloudWatch alarms and SNS topics. You must also have a Rootly account with access to Alert Sources.

## Setup Instructions

<Steps>
  <Step title="Create an Alert Source in Rootly">
    Begin by creating a CloudWatch alert source in Rootly. Navigate to **Settings** → **Alert Sources** and click **Add Alert Source**. Select **CloudWatch** and provide a descriptive name, such as “Production CloudWatch Alarms.”

    You may optionally configure default alert urgency, assign owner groups, or define an alert template. Once the alert source is saved, copy the webhook URL provided by Rootly.

    ```txt theme={null}
    https://webhooks.rootly.com/webhooks/incoming/cloud_watch_webhooks?secret=YOUR_SECRET_KEY
    ```

    <Callout icon="key" color="#DBEAFE">
      The webhook secret authenticates incoming requests from Amazon SNS. Treat this value as sensitive and rotate it if it is exposed.
    </Callout>
  </Step>

  <Step title="Create an SNS Topic">
    Create an Amazon SNS topic to receive CloudWatch alarm notifications. In the AWS SNS Console, create a new topic using the **Standard** topic type and give it a clear, descriptive name such as `rootly-cloudwatch-alerts`.

    This SNS topic acts as the delivery mechanism between CloudWatch and Rootly.
  </Step>

  <Step title="Subscribe Rootly to the SNS Topic">
    Open the SNS topic and navigate to the **Subscriptions** tab. Create a new subscription using the **HTTPS** protocol and paste the Rootly webhook URL into the endpoint field.

    AWS sends a subscription confirmation request to the webhook endpoint. Rootly automatically attempts to confirm this request, and the subscription typically transitions to **Confirmed** within a few seconds.

    <Info>
      If the subscription remains in a pending state, verify that the webhook endpoint is reachable and that no network restrictions are blocking AWS SNS traffic.
    </Info>
  </Step>

  <Step title="Configure a CloudWatch Alarm">
    In the CloudWatch Console, navigate to **All alarms** and create a new alarm. Select the metric to monitor and define the alarm conditions, including thresholds and evaluation periods.

    Configure the alarm to send notifications to the SNS topic for both the **In alarm** and **OK** states. This ensures alerts are created and resolved automatically in Rootly.
  </Step>

  <Step title="Test the Integration">
    Trigger the CloudWatch alarm or allow it to trigger naturally. Verify that a new alert appears in Rootly with the source set to CloudWatch.

    When the alarm returns to the `OK` state, confirm that the alert is automatically resolved.
  </Step>
</Steps>

## Alert Mapping and Behavior

Rootly extracts key fields from CloudWatch alarm notifications and maps them to alert attributes. The alarm ARN is used as the external identifier, which allows Rootly to deduplicate alerts and correctly match resolve events. The alarm name, metric name, and state change reason are included in the alert summary.

The alert summary is generated automatically and typically follows the format shown below.

```txt theme={null}
{MetricName} - {NewStateReason}
```

For example:

```txt theme={null}
CPUUtilization - Threshold Crossed: 1 datapoint [85.5] was greater than the threshold (80.0).
```

<Warning>
  **CloudWatch alarm tags are not included in the SNS payload.** Amazon's CloudWatch → SNS notification pipeline does not propagate the tags you set on the alarm resource, so Rootly cannot read them and cannot turn them into alert labels. If you need tag-like metadata on a Rootly alert for routing, use the patterns in [Passing Metadata for Routing](#passing-metadata-for-routing) below.
</Warning>

## Passing Metadata for Routing

CloudWatch alarm tags are not delivered to Rootly through SNS — this is an AWS-side limitation, not a Rootly limitation. There are three supported patterns for getting routing metadata (team, environment, severity, service) onto Rootly alerts that originate from CloudWatch.

### Pattern 1: Structured AlarmName Conventions

The `AlarmName` field is included in every SNS notification and is the simplest place to encode metadata. Adopt a positional convention like `<team>-<env>-<service>-<severity>` — for example `platform-prod-api-latency-p1` — then use the alert template on your CloudWatch Alert Source to extract each segment into an Alert Field (or set them as labels) using Liquid:

```liquid theme={null}
Team:     {{ alert.data.Message.AlarmName | split: "-" | first }}
Severity: {{ alert.data.Message.AlarmName | split: "-" | last }}
```

Once those values exist on the alert as fields, build an [Alert Route](/alerts/alert-routing) that matches on the field value to target the right service, escalation policy, or team. Routing rules evaluate Alert Fields or JSONPath into the raw payload — they don't evaluate Liquid templates directly, so this two-step (extract into a field with Liquid, then route on the field) is the pattern.

This is the lowest-effort approach and needs no new infrastructure. The trade-off is that AlarmName length and format are constrained, and you lose flexibility once you have more than 3–4 dimensions to encode.

### Pattern 2: AlarmDescription Key-Value Metadata

The `AlarmDescription` field is also delivered through SNS and accepts free-form text up to AWS's character limit. Put key-value pairs in the description (one per line, `key: value` format works well):

```text theme={null}
team: platform
env: prod
severity: high
runbook: https://wiki/runbooks/api-latency
```

In the Rootly alert template, parse the description with Liquid to extract each value into an Alert Field (or label) on the resulting alert, then [route](/alerts/alert-routing) on those fields. If you'd rather skip the alert-template step entirely, an Alert Route can also match against a JSONPath expression directly against the raw payload (for example `$.Message.AlarmDescription`) using contains/regex matchers — useful when you only need to match on the description content for routing without persisting structured fields on the alert.

This pattern scales better than AlarmName encoding and keeps the alarm name human-readable.

### Pattern 3: Lambda Enrichment (Most Flexible)

If you need access to the actual CloudWatch alarm **tags** — not metadata you've embedded in the name or description — insert a Lambda function between SNS and Rootly. The Lambda receives the SNS notification, calls `cloudwatch:ListTagsForResource` against the alarm ARN, enriches the payload with the tag values, and posts the enriched payload to a [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source) in Rootly.

Flow:

```text theme={null}
CloudWatch alarm → SNS topic → Lambda function → Rootly Generic Webhook
```

The Lambda needs IAM permissions for `cloudwatch:ListTagsForResource` (or `cloudwatch:DescribeAlarms` if you also need other alarm attributes). This pattern is the only way to access real CloudWatch tags from Rootly, and it's the right choice when you already standardize on tags across many AWS resources and want a single source of truth.

<Warning>
  **Preserve dedup and auto-resolve semantics when you move off the native CloudWatch source.** The native CloudWatch Alert Source automatically uses the alarm ARN as the external identifier (for deduplication) and maps `ALARM` → triggered / `OK` → resolved (for auto-resolution). When you switch to a Generic Webhook Alert Source, those mappings are no longer automatic — your Lambda needs to set them explicitly in the payload it posts to Rootly:

  * **External identifier:** include `AlarmArn` (or a stable equivalent) as the dedup key so repeated alarm triggers update the same Rootly alert instead of creating duplicates.
  * **State mapping:** translate the CloudWatch `NewStateValue` field (`ALARM`, `OK`, `INSUFFICIENT_DATA`) into the alert state field your Generic Webhook source expects — typically `triggered` for `ALARM` and `resolved` for `OK`.

  See the [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source) reference for the expected payload shape and the auto-resolution conditions you can configure on the source.
</Warning>

## Advanced Configuration

### Alert Templates

Alert templates allow you to control how CloudWatch alerts appear in Rootly. Templates are configured from the Alert Source settings and support Liquid templating, which makes it possible to dynamically generate alert content from the CloudWatch alarm payload.

Commonly used template variables include the alarm name, alarm ARN, metric name, state change reason, and timestamp. These variables can be combined to produce descriptive alert titles, detailed descriptions, and direct links back to the AWS Console.

### Alert Routing

CloudWatch alerts can be routed automatically using Rootly alert routes. Routing rules may be defined using alarm names, metric names, regions, namespaces, AlarmDescription content, or any other field actually included in the SNS payload. Routes can target services, escalation policies, or teams, ensuring that alerts are delivered to the appropriate responders without manual intervention.

If you need to route by team, environment, severity, or other tag-style metadata, see [Passing Metadata for Routing](#passing-metadata-for-routing) above — CloudWatch alarm tags themselves are not in the SNS payload, so routing rules cannot reference them directly.

### Deduplication and Resolution

Rootly deduplicates CloudWatch alerts using the alarm ARN as the external identifier. If an alarm triggers multiple times while an alert remains unresolved, Rootly updates the existing alert instead of creating duplicates. When the alarm transitions back to the `OK` state, Rootly automatically resolves the corresponding alert.

### Notification Targets

In addition to default routing rules, CloudWatch alarms can be sent directly to specific notification targets using a specialized webhook endpoint.

```txt theme={null}
https://webhooks.rootly.com/webhooks/incoming/cloud_watch_webhooks/notify/{notification_target_type}/{notification_target_id}?secret=YOUR_SECRET_KEY
```

The notification target type must be one of `Service`, `EscalationPolicy`, or `Group`. The notification target ID must be replaced with the UUID of the corresponding resource.

### Webhook Payload Structure

CloudWatch delivers alarm notifications to Amazon SNS, which then forwards them to Rootly. The SNS payload includes metadata about the message and a `Message` field containing a JSON-encoded representation of the CloudWatch alarm state change. Rootly automatically parses this message and extracts the relevant alarm data for alert creation and resolution.

### Security Considerations

Rootly webhook endpoints require HTTPS and use a secret key to authenticate incoming requests. SNS message signatures are verified to ensure authenticity. If IP allowlisting is enabled for your Rootly instance, ensure that AWS SNS IP ranges are permitted.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Why are CloudWatch alerts not being created in Rootly?" icon="circle-exclamation">
    Verify that the SNS subscription is confirmed and that the webhook URL configured in SNS exactly matches the one provided by Rootly. Ensure that the CloudWatch alarm is actively entering the `ALARM` state and review the alert source status in Rootly to confirm whether recent events have been received.
  </Accordion>

  <Accordion title="Why are CloudWatch alerts not being resolved automatically?" icon="rotate">
    Ensure that the CloudWatch alarm is configured to send `OK` notifications to the same SNS topic used for alarm notifications. Rootly relies on the alarm ARN to match resolve events, so confirm that the alarm ARN has not changed since the alert was created.
  </Accordion>

  <Accordion title="Why is the SNS subscription stuck in Pending confirmation?" icon="signal">
    Confirm that the webhook endpoint is reachable over HTTPS and that no firewall rules or IP allowlisting restrictions are blocking AWS SNS traffic. Also verify that the webhook URL is correctly formatted and includes the required secret parameter.
  </Accordion>

  <Accordion title="My CloudWatch alarm tags aren't appearing as labels on the Rootly alert" icon="tags">
    Expected behavior — CloudWatch alarm tags are not included in the SNS notification payload, so they never reach Rootly. This is an AWS-side limitation. To get tag-like metadata onto Rootly alerts, use one of the patterns in [Passing Metadata for Routing](#passing-metadata-for-routing): encode the values in AlarmName, put key-value pairs in AlarmDescription, or run a Lambda between SNS and Rootly that looks up the alarm's tags via `cloudwatch:ListTagsForResource` and enriches the payload before posting to a Generic Webhook Alert Source.
  </Accordion>
</AccordionGroup>

## Best Practices

* Use clear and descriptive alarm names. The AlarmName is the most-visible field on the resulting Rootly alert and the easiest place to encode routing metadata using a structured naming convention. Extract each segment into an Alert Field via the alert template, then route on those fields.
* Put key-value metadata in the AlarmDescription field when you need more than 3–4 dimensions to route on. It carries through the SNS payload and can be parsed with Liquid into Alert Fields, or matched directly via JSONPath in an Alert Route.
* If your existing observability practice relies on consistent CloudWatch tags across teams, use [Lambda enrichment](#pattern-3-lambda-enrichment-most-flexible) to bring those tag values onto Rootly alerts.
* Configure alert routing rules to ensure alerts reach the appropriate teams.
* Periodically test alarms to validate that the integration continues to function as expected.

For additional assistance, consult the Rootly documentation or contact Rootly Support. You may also refer to AWS CloudWatch and Amazon SNS documentation for more information about alarm and notification configuration.
