Skip to main content
This guide shows you how to publish CloudWatch alarms defined in AWS CDK to the scaling.cloud AWS integration so that incidents open on OK → ALARM and auto-resolve on ALARM → OK. If you set up alarms in the console or with Terraform instead, see Ingest CloudWatch Alarms. For an overview of the integration, see AWS CloudWatch.

Why both transitions matter

The integration opens an incident when an alarm transitions to ALARM and resolves the matching incident when the same alarm transitions back to OK. If your CDK only wires the alarm action and forgets the OK action, CloudWatch never publishes the recovery transition to SNS — your incident stays open forever even after the underlying metric recovers. This is the single most common CDK mistake when connecting alarms to scaling.cloud. The patterns below avoid it by default.

Prerequisites

You should already have the AWS integration created in scaling.cloud and the SNS topic + HTTPS subscription in place. If you don’t, follow the first four steps of Ingest CloudWatch Alarms and then come back here to wire your alarms. You’ll need:
  • An existing SNS topic subscribed to your scaling.cloud webhook URL, with SignatureVersion=2 (scaling.cloud rejects the SNS default of 1).
  • A CDK app using aws-cdk-lib v2 (TypeScript). The snippets below were written against aws-cdk-lib@^2.250.
In CDK, you reference the topic by its ARN — usually exported from the stack that owns it, or imported via Topic.fromTopicArn.
If your topic is also created in CDK, set signatureVersion: '2' on the Topic directly so every subscription inherits RSA-SHA256 — no per-subscription override needed.
For an existing subscription you can’t recreate, update it in place with aws sns set-subscription-attributes --attribute-name SignatureVersion --attribute-value 2.
The same topic can carry both ALARM and OK notifications for many alarms — you do not need one topic per transition. One topic per scaling.cloud component is the right granularity.

Approach A: cdk-monitoring-constructs

If you’re using cdk-monitoring-constructs (the MonitoringFacade / SLO-style API), wire the OK transition by passing both onAlarmTopic and onOkTopic to SnsAlarmActionStrategy. By default the strategy only sets onAlarmTopic.
Every alarm produced through this facade — monitorLambdaFunction, monitorApiGateway, monitorSqsQueue, custom metrics — inherits both topics. You configure the wiring once.
SnsAlarmActionStrategy accepts onAlarmTopic, onOkTopic, and onInsufficientDataTopic independently. Omitting onOkTopic is the default — and the default is wrong for scaling.cloud. Always set it explicitly.

Approach B: raw aws-cdk-lib/aws-cloudwatch

If you build Alarm instances directly, call both addAlarmAction and addOkAction with the same SnsAction. Scattering those two calls everywhere is error-prone, so wrap them in a small helper and route every alarm through it:
A helper is preferable to scattering addAlarmAction and addOkAction calls across the codebase. The next person reviewing your stack only has to check that every alarm flows through routeAlarmToScaling, not that both methods are called everywhere.

Set severity from the alarm description

scaling.cloud parses an optional severity marker from the alarm’s AlarmDescription field and uses it for the opened incident. The marker uses the familiar [Pn] notation as a severity-rank shorthand — scaling.cloud has a single severity dial and no separate “priority” field, so [P1][P4] map directly onto the four severity levels: If the description is empty or has no recognised prefix, the incident defaults to high. The marker can appear anywhere in the description, but convention is to put it at the start so the level is obvious in CloudWatch too:
The full description (including the marker) is also forwarded into the incident’s body so responders see the original CloudWatch context.

Route to a component from the alarm description

By default every alarm on a topic lands on the integration’s fallback component. To fan a single topic out across many components, add a [component:…] tag to the alarm description with the target component’s name or one of its aliases; scaling.cloud resolves it (case-insensitively) to the owning component and pages that component’s escalation policy. SNS notifications don’t carry alarm tags, so the description is the in-band channel — the same place the [Pn] severity marker lives, and the two can coexist:
A [component:…] value that matches no component name or alias falls back to the integration’s fallback component — a typo never drops an alert.

Verification

After cdk deploy, confirm the OK transition is actually wired before you trust the auto-resolve path.
1

Check the synthesized template

Run cdk synth and inspect the generated CloudFormation. Every AWS::CloudWatch::Alarm resource should have both AlarmActions and OKActions populated with your SNS topic ARN:
If OKActions is missing or empty on any alarm, that alarm’s incident will never auto-resolve.
2

Confirm in the AWS console

Open any deployed alarm in the CloudWatch console. Under Actions, the In alarm and OK rows should both list your SNS topic. Insufficient data can be left empty — the integration ignores those notifications by design.
3

Force a transition end-to-end

Temporarily lower an alarm’s threshold (or trigger the underlying condition) so it transitions OK → ALARM. Within a few seconds a new incident appears in scaling.cloud on the mapped component. Restore the threshold so the alarm returns to OK — the open incident should auto-resolve.

Common pitfalls

scaling.cloud enforces topic-ARN pinning per integration: the first valid delivery decides which topic ARN is allowed, and every subsequent delivery’s TopicArn is checked against the pinned value. If you migrate to a new topic, recreate the integration so the pin can be re-set.

See also