# AWS Cloudwatch Integration

## Amazon CloudWatch Integration

Amazon CloudWatch is a monitoring and observability service built for AWS cloud resources, providing real-time metrics, alarms, and automated actions across your entire AWS infrastructure.

### Overview

This guide walks you through integrating Amazon CloudWatch with our alert management platform. CloudWatch alarm notifications are delivered through Amazon Simple Notification Service (SNS) as HTTP POST webhooks. The `Message` field inside the SNS envelope contains a JSON-encoded string with the full alarm details including alarm name, state change, trigger condition, and affected resource.

### Integration Flow

1. CloudWatch continuously monitors AWS resource metrics (CPU, memory, disk, network, custom metrics, etc.).
2. When a metric violates a configured alarm threshold, CloudWatch changes the alarm state to **ALARM** and publishes a notification to the linked SNS topic.
3. The SNS topic delivers the notification payload to the subscribed HTTPS endpoint (our platform webhook).
4. When the metric returns to normal, CloudWatch changes the alarm state to **OK** and publishes a recovery notification through the same SNS topic.

***

### Webhook Payload Schema

CloudWatch alarm notifications are wrapped in an **SNS notification envelope**. The payload structure is standardized by AWS and cannot be customized.

#### SNS Envelope Fields

| Field            | Type   | Required | Description                                                                 |
| ---------------- | ------ | -------- | --------------------------------------------------------------------------- |
| Type             | string | Yes      | SNS message type (`Notification`, `SubscriptionConfirmation`)               |
| MessageId        | string | Yes      | Unique identifier for the SNS message                                       |
| TopicArn         | string | Yes      | ARN of the SNS topic that published the message                             |
| Subject          | string | No       | Alert summary, e.g. `ALARM: "high-cpu-test-alarm" in US East (N. Virginia)` |
| Message          | string | Yes      | JSON-encoded string containing the full CloudWatch alarm details            |
| Timestamp        | string | Yes      | ISO 8601 timestamp of the notification                                      |
| SignatureVersion | string | No       | Version of the SNS message signature                                        |
| Signature        | string | No       | Base64-encoded signature for message verification                           |
| SigningCertURL   | string | No       | URL of the certificate used to sign the message                             |
| UnsubscribeURL   | string | No       | URL to unsubscribe from the SNS topic                                       |

#### Inner Message Fields (JSON-encoded inside `Message`)

| Field            | Type   | Description                                                        |
| ---------------- | ------ | ------------------------------------------------------------------ |
| AlarmName        | string | Name of the CloudWatch alarm                                       |
| AlarmDescription | string | Description of the alarm                                           |
| AWSAccountId     | string | AWS account ID                                                     |
| NewStateValue    | string | Current alarm state: `ALARM`, `OK`, or `INSUFFICIENT_DATA`         |
| NewStateReason   | string | Human-readable explanation of the state change                     |
| StateChangeTime  | string | Timestamp of the state change                                      |
| Region           | string | AWS region where the alarm is configured                           |
| AlarmArn         | string | Full ARN of the CloudWatch alarm                                   |
| OldStateValue    | string | Previous alarm state                                               |
| Trigger          | object | Object containing MetricName, Namespace, Threshold, Dimensions etc |

***

### Severity / Status Mapping

CloudWatch does not have a native severity field. The alarm state is used to determine the alert status:

| CloudWatch State   | Platform Status | Description                                    |
| ------------------ | --------------- | ---------------------------------------------- |
| ALARM              | PROBLEM         | Threshold breached, resource is in alarm state |
| OK                 | RECOVERY        | Metric returned to normal, alarm cleared       |
| INSUFFICIENT\_DATA | PROBLEM         | Not enough data to evaluate the alarm          |

**Priority Mapping** Priority is inferred from the alarm name. To enable automatic priority mapping, include one of the following keywords in your alarm name:

* `CRITICAL` → Critical
* `HIGH` → High
* `WARN` or `WARNING` → Medium
* `LOW` or `INFO` → Low

Alarms without these keywords default to **Medium** priority. Example: `prod-database-CRITICAL-cpu-alarm`

***

### Alert Payload Examples

#### Raised (ALARM)

This payload is sent when a CloudWatch alarm is triggered. The `Subject` field begins with `ALARM:` and the inner `NewStateValue` is `ALARM`.

![](https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FbR6u3pbxzGXJXGFF5mLy%2Fimage.png?alt=media\&token=b2ff86fc-f0ce-429e-b17a-6b0b697ed637)

ALARM payload received at webhook.site

```json
{
  "Type": "Notification",
  "MessageId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "TopicArn": "arn:aws:sns:region:ACCOUNT_ID:TOPIC_NAME",
  "Subject": "ALARM: \"example-alarm-name\" in REGION",
  "Message": "{\"AlarmName\":\"example-alarm-name\",\"AlarmDescription\":\"Test alarm description\",\"AWSAccountId\":\"ACCOUNT_ID\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: example reason\",\"StateChangeTime\":\"2026-02-10T17:18:34.056+0000\",\"Region\":\"REGION\",\"AlarmArn\":\"arn:aws:cloudwatch:region:ACCOUNT_ID:alarm:example-alarm-name\",\"OldStateValue\":\"INSUFFICIENT_DATA\",\"Trigger\":{\"MetricName\":\"ExampleMetric\",\"Namespace\":\"AWS/Service\",\"StatisticType\":\"Statistic\",\"Statistic\":\"AVERAGE\",\"Unit\":null,\"Dimensions\":[{\"value\":\"example-resource\",\"name\":\"ResourceName\"}],\"Period\":86400,\"EvaluationPeriods\":1,\"DatapointsToAlarm\":1,\"ComparisonOperator\":\"GreaterThanThreshold\",\"Threshold\":0.0}}",
  "Timestamp": "2026-02-10T17:18:34.096Z",
  "SignatureVersion": "1",
  "Signature": "REDACTED",
  "SigningCertURL": "https://sns.region.amazonaws.com/SimpleNotificationService.pem",
  "UnsubscribeURL": "https://sns.region.amazonaws.com/?Action=Unsubscribe"
}
```

#### Cleared (OK)

This payload is sent when the alarm returns to normal. The `Subject` field begins with `OK:` and the inner `NewStateValue` is `OK`.

```json
{
  "Type": "Notification",
  "MessageId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "TopicArn": "arn:aws:sns:region:ACCOUNT_ID:TOPIC_NAME",
  "Subject": "OK: \"example-alarm-name\" in REGION",
  "Message": "{\"AlarmName\":\"example-alarm-name\",\"AlarmDescription\":\"Test alarm description\",\"AWSAccountId\":\"ACCOUNT_ID\",\"NewStateValue\":\"OK\",\"NewStateReason\":\"Recovery reason\",\"StateChangeTime\":\"2026-02-10T17:28:07.334+0000\",\"Region\":\"REGION\",\"AlarmArn\":\"arn:aws:cloudwatch:region:ACCOUNT_ID:alarm:example-alarm-name\",\"OldStateValue\":\"ALARM\",\"Trigger\":{\"MetricName\":\"ExampleMetric\",\"Namespace\":\"AWS/Service\",\"StatisticType\":\"Statistic\",\"Statistic\":\"AVERAGE\",\"Unit\":null,\"Dimensions\":[{\"value\":\"example-resource\",\"name\":\"ResourceName\"},{\"value\":\"example-dimension\",\"name\":\"DimensionType\"}],\"Period\":86400,\"EvaluationPeriods\":1,\"DatapointsToAlarm\":1,\"ComparisonOperator\":\"GreaterThanThreshold\",\"Threshold\":0.0}}",
  "Timestamp": "2026-02-10T17:28:07.380Z",
  "SignatureVersion": "1",
  "Signature": "REDACTED",
  "SigningCertURL": "https://sns.region.amazonaws.com/SimpleNotificationService.pem",
  "UnsubscribeURL": "https://sns.region.amazonaws.com/?Action=Unsubscribe"
}
```

***

### Installation & Configuration

#### Step 1: Create an Alert Source in the Platform

1. Log in to the alert management platform.
2. Navigate to **Integrations** → **Add Integration**.
3. Select **Amazon CloudWatch** as the provider.
4. Name the integration (e.g., `Production AWS Alerts`).
5. Save and copy the generated **Webhook URL** and **Token**.

#### Step 2: Create an SNS Topic in AWS

1. Log in to the **AWS Management Console**.
2. Navigate to **Simple Notification Service (SNS)** → **Topics**.
3. Click **Create topic**.
4. Select type: **Standard** (not FIFO).
5. Enter a topic name (e.g., `oncall-cloudwatch-alerts`).
6. Leave all other settings as default.
7. Click **Create topic**.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2F12k7rmSPYshnC9LxBiPf%2FEkran%20Resmi%202026-02-25%2015.14.48.png?alt=media&#x26;token=0ab26669-24ee-4fa6-b965-f90f40cc6cbb" alt=""><figcaption></figcaption></figure>

* SNS Create Topic page (Standard type selected, topic name entered)

8. Note the **Topic ARN** displayed on the topic detail page.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FnV5KjyjAopkfN0EKClmA%2FEkran%20Resmi%202026-02-25%2015.15.59.png?alt=media&#x26;token=ef017db1-b117-4c36-b536-d39029e92618" alt=""><figcaption></figcaption></figure>

&#x20;

* SNS Topic created with ARN visible

#### Step 3: Create an SNS Subscription (Webhook Endpoint)

1. On the topic detail page, go to the **Subscriptions** tab.
2. Click **Create subscription**.
3. **Topic ARN**: Pre-filled with the topic ARN (do not change).
4. **Protocol**: Select **HTTPS**.
5. **Endpoint**: Paste your platform webhook URL (e.g., `https://<your-platform>/functions/v1/webhook`).
6. **Enable raw message delivery**: Leave **unchecked** (disabled). This ensures the full SNS envelope is delivered.
7.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FeOOfdFRrpUZvOm9fghJ0%2FEkran%20Resmi%202026-02-25%2015.17.48.png?alt=media&#x26;token=a0e95f1c-af38-494f-9793-e3ea32118294" alt=""><figcaption></figcaption></figure>

* Click **Create subscription**.

1. The subscription status will initially show **PendingConfirmation**.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2F50T2sptXIprCKgw8Buvk%2FEkran%20Resmi%202026-02-25%2015.19.07.png?alt=media&#x26;token=ff0bfc35-66d2-4dd9-b7f8-6785232f7523" alt=""><figcaption></figcaption></figure>

&#x20;

* SubscriptionConfirmation payload received at webhook.site

9. The platform will automatically confirm the subscription. If using a third-party test endpoint (e.g., webhook.site), manually open the `SubscribeURL` from the received payload in your browser.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2F12f1b8Oo6NZnHamt3YNW%2FEkran%20Resmi%202026-02-25%2015.19.58.png?alt=media&#x26;token=a548d941-0095-48d1-b2c5-f7b49739e249" alt=""><figcaption></figcaption></figure>

&#x20;

* SubscribeURL opened in browser showing confirmation XML response

10. After refreshing, the subscription status should change to **Confirmed**.

&#x20;

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FhUoQBtt2XhZCa5idkXAz%2Fimage.png?alt=media&#x26;token=8254cb6d-fd45-471c-bdd7-40e6dd521c01" alt=""><figcaption></figcaption></figure>

* SNS Subscription status: Confirmed

#### Step 4: Create a CloudWatch Alarm and Link to the SNS Topic

1. Navigate to **CloudWatch** → **Alarms** → **All alarms**.
2. Click **Create alarm**.
3. Click **Select metric** and choose the metric you want to monitor (e.g., EC2 CPUUtilization, RDS connections, S3 object count, or a custom metric).

   <figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FZJeXwiqyBsCahrBnh7EO%2FEkran%20Resmi%202026-02-12%2018.30.15.png?alt=media&#x26;token=b5a8e31a-0993-4fc1-88bc-f001248c43df" alt=""><figcaption></figcaption></figure>

   <figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2F6qzk1dowlJeZWiq6XCXd%2FEkran%20Resmi%202026-02-12%2018.30.57.png?alt=media&#x26;token=77bf18dc-404e-4d80-94e9-45431f7036e5" alt=""><figcaption></figcaption></figure>
4. Configure the alarm condition:
   * **Period**: Select an appropriate evaluation period (e.g., 1 minute, 5 minutes).
   * **Threshold type**: Static.
   * **Condition**: Greater than (or your preferred operator).
   * **Threshold value**: Set the desired threshold.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FAH6wnzf2wApNaMlMJi1O%2FEkran%20Resmi%202026-02-25%2015.21.20.png?alt=media&#x26;token=06d45d32-b62e-488a-8981-9f9e815f0ace" alt=""><figcaption></figcaption></figure>

5. Click **Next** to configure actions.
6. Under **Notification**, configure **two** notification actions:

   **Action 1 — In alarm (Trigger):**

   * Alarm state trigger: **In alarm**
   * Select an existing SNS topic: Choose the topic created in Step 2 (e.g., `oncall-cloudwatch-alerts`)

   **Action 2 — OK (Recovery):**

   * Click **Add notification**
   * Alarm state trigger: **OK**
   * Select an existing SNS topic: Choose the same topic

&#x20;

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2F1AcIQXZGJ8qDwoEPp2WK%2Fimage.png?alt=media&#x26;token=bb78320b-9ffd-4611-a7a6-44313314d2e8" alt=""><figcaption></figcaption></figure>

* Configure actions page showing both In Alarm and OK notification actions

7. Click **Next**, name your alarm, add a description, and click **Create alarm**.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FQD2BlSFbQ6ihIZ1LGxgz%2FEkran%20Resmi%202026-02-25%2015.23.25.png?alt=media&#x26;token=7b7b2b77-8011-4e24-a514-ff763b0eda81" alt=""><figcaption></figcaption></figure>

&#x20;

* Alarm successfully created (state: Insufficient data, Actions enabled)

> **Important:** Both **In alarm** and **OK** notification actions must be configured to ensure proper alert lifecycle handling and automatic recovery.

***

### Testing

Once the alarm is triggered, you can verify the integration by checking the received payloads.

#### Verify ALARM Notification

When the alarm condition is met, CloudWatch will automatically send an ALARM notification through SNS to your webhook endpoint.

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FmA4gZbUlJ3CyQoSnwwmu%2FEkran%20Resmi%202026-02-25%2015.25.41.png?alt=media&#x26;token=c8c531ad-b30b-435b-8c5f-2993a84df904" alt=""><figcaption></figcaption></figure>

* ALARM payload received at webhook.site (Type: Notification, Subject starts with "ALARM:")

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FogBxQ7XvudihaEI39r9p%2Fimage.png?alt=media&#x26;token=5a5b36c3-1280-4307-9826-25ec5c74aa07" alt=""><figcaption></figcaption></figure>

* CloudWatch dashboard showing alarm in "In alarm" state

#### Trigger a Manual OK (Recovery) via CloudShell

To test the recovery flow, use **AWS CloudShell** (available in the AWS Console top toolbar) to manually set the alarm state to OK:

```bash
aws cloudwatch set-alarm-state \
  --alarm-name "high-cpu-test-alarm" \
  --state-value OK \
  --state-reason "Recovery test - CPU back to normal" \
  --region us-east-1
```

&#x20;

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FHV27b4vXHfeI6UoJvfTU%2FEkran%20Resmi%202026-02-25%2015.26.23.png?alt=media&#x26;token=a108be80-74fe-4ea2-9e50-2fe75e1dc05b" alt=""><figcaption></figcaption></figure>

* CloudShell with set-alarm-state OK command executed, alarm state changed to OK

<figure><img src="https://4108595529-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimJRSa33y5Ej6rwXrBeA%2Fuploads%2FVA8CG3Wz7yIHjuJKHxE1%2FEkran%20Resmi%202026-02-25%2015.29.58.png?alt=media&#x26;token=b15b731c-3ada-4534-837c-1a86ba446272" alt=""><figcaption></figcaption></figure>

#### Verification Checklist

Verify that:

1. An **ALARM** notification is received by the platform (status: PROBLEM).
2. An **OK** notification is received after recovery (status: RECOVERY).
3. Both payloads contain the correct `Type: "Notification"`, `TopicArn`, `Subject`, and `Message` fields.

***

### Troubleshooting

| Issue                         | Possible Cause                                        | Resolution                                                                                       |
| ----------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| No alerts received            | SNS subscription not confirmed                        | Check subscription status in SNS Console. Re-create subscription if stuck on PendingConfirmation |
| No alerts received            | Alarm notification action not configured              | Ensure the SNS topic is attached to the alarm's In Alarm action                                  |
| Recovery alerts missing       | OK notification action not configured                 | Add the SNS topic to the alarm's OK action via **Add notification**                              |
| SubscriptionConfirmation only | Endpoint did not confirm the subscription             | Open the `SubscribeURL` in a browser or ensure your platform auto-confirms                       |
| Payload format unexpected     | Raw message delivery is enabled                       | Disable "Enable raw message delivery" in the SNS subscription settings                           |
| Delayed notifications         | Alarm evaluation period too long                      | Reduce the alarm's Period setting for faster evaluation                                          |
| Invalid payload error         | Payload does not match the expected CloudWatch schema | Verify the subscription is HTTPS and raw delivery is disabled                                    |
| Duplicate notifications       | Multiple SNS subscriptions for the same endpoint      | Remove duplicate subscriptions from the SNS topic                                                |
