AWS Synthetic Monitoring: CloudWatch Synthetics Explained

AWS CloudWatch Synthetics lets you create scripted checks called canaries that run against your application on a schedule you define. Unlike waiting for real users to report problems, canaries test your login flow, API endpoints, and checkout paths continuously, even at 3 AM with zero traffic. When something breaks, you find out immediately rather than after the Monday morning rush.

What synthetic monitoring is

Synthetic monitoring means running automated, scripted interactions against your application on a fixed schedule, regardless of whether any real users are active. These scripts simulate what a user or API client would do: load a page, submit a form, call an endpoint, and verify the response.

The key distinction is that synthetic monitoring is proactive. A basic HTTP health check tells you whether a server responds with 200. A synthetic canary goes further: it checks that your login page loads, the form submits, the API returns the right shape, and no error silently blocks the flow.

Why it matters

CloudWatch metrics and logs tell you about failures that have already happened to real traffic. But if your checkout flow breaks at 2 AM when no one is shopping, your metrics stay silent until the first real user hits the error.

Synthetic monitoring closes that gap. It is especially useful for:

  • Detecting outages outside business hours when real traffic is low
  • Verifying critical user paths end-to-end: login, checkout, password reset
  • Measuring latency consistently from a fixed AWS region over time
  • Checking third-party API dependencies your app relies on
  • Generating SLA evidence that your service met its uptime commitments
  • Testing across

    multiple AWS regions

    to catch geographic degradation early

Simple explanation

Think of a canary like a mystery shopper on a timer. Every five minutes, the mystery shopper visits your store, adds something to the cart, and tries to check out. If the checkout page is broken, the cart is empty, or the payment form never loads, the mystery shopper reports back immediately. Real customers have not arrived yet, but you already know something is wrong.

That is exactly what a CloudWatch canary does. It is a small script that AWS runs on a schedule, knocking on your application’s door and checking that everything opens correctly. When it fails, a CloudWatch alarm fires and your team gets notified.

How this is different from a basic ping

A ping or a Route 53 health check tells you a server responded. A canary tells you whether your application actually worked. Your server can return HTTP 200 with a blank page, an error message in the HTML, or a login form that submits to a broken API. Only a synthetic check that inspects the response body and simulates the user journey will catch those failures.

How CloudWatch Synthetics works

CloudWatch Synthetics manages the execution of canary scripts for you. Under the hood, each canary runs as an AWS Lambda function. You write the script; AWS handles the infrastructure, scheduling, and result storage.

The lifecycle of a canary run:

  1. Create the canary — write a Node.js or Python script and upload it via the console, CLI, or an IaC tool.

  2. Runs on schedule — CloudWatch invokes the Lambda on your defined cadence, for example every 5 minutes.

  3. Publishes metrics and artifacts — pass/fail results, timing data, and screenshots go to CloudWatch metrics and an S3 bucket automatically.

  4. Triggers alarms — a CloudWatch alarm on the SuccessPercent metric notifies you when runs start failing.

  5. Investigate failures — inspect screenshots, HAR files, and logs in the CloudWatch Synthetics console or your S3 bucket to pinpoint what broke.

Canaries can make plain HTTP requests (fast and cheap) or launch a headless Chromium browser via Puppeteer for full UI testing. Use HTTP-only mode for API endpoints. Use the browser runtime when you need to test JavaScript rendering, multi-step forms, or visual correctness.

The alarm setting most people miss

When you create a CloudWatch alarm on SuccessPercent, also set treat-missing-data breaching. If the canary itself fails to run due to a permissions error or code bug, CloudWatch has no data to evaluate. By default, missing data is treated as OK, meaning the alarm stays green and you never get notified. This setting turns a silent failure into a loud one.

When to use this

CloudWatch Synthetics is the right tool when you need:

  • Login flow monitoring — verify authentication works continuously, including during off-peak hours when real traffic is minimal

  • Checkout path coverage — confirm the full purchase flow completes without JavaScript errors or silent API failures

  • API health endpoint checks — validate that public or internal APIs return correct responses within expected latency bounds

  • Third-party dependency monitoring — detect when an upstream payment provider or mapping API degrades before it impacts your users

  • Off-hours monitoring — maintain full coverage when real traffic is too low to trigger metric-based alarms

  • Regional availability checks — run canaries in multiple AWS regions to catch geographic failover issues alongside

    Route 53 routing policies

Multi-region canaries

A canary deployed in us-east-1 only tests availability from that region. If you serve users globally, deploy identical canaries in multiple regions such as us-east-1, eu-west-1, and ap-southeast-1. Each one fires its own alarm independently, so a region-specific outage shows up before it affects your users worldwide.

When not to use this

Synthetic monitoring is one layer of observability, not a replacement for the rest of the stack. Using canaries for tasks they are not designed for leads to gaps you would not expect.

  • Not a substitute for RUM. Canaries run from a fixed AWS location with clean network conditions. They do not reflect what real users experience on mobile, slow connections, or older devices.

  • Not a tracing tool. Canaries confirm that a flow passes or fails, but cannot trace which microservice caused a slowdown. Use AWS X-Ray and

    distributed tracing

    for that.

  • Not a log analysis tool. For deep error investigation, CloudWatch Logs and

    log-based metrics

    are more appropriate.

  • Not infrastructure monitoring. CPU, memory, and database performance belong in CloudWatch metrics or

    Performance Insights

    , not canary scripts.

  • Not ideal for Lambda-specific failures. For Lambda cold starts and error debugging, see

    Monitoring Lambda in AWS

    directly.

CloudWatch Synthetics vs CloudWatch RUM vs Route 53 health checks

FeatureCloudWatch SyntheticsCloudWatch RUMRoute 53 health checks
Data sourceScripted bots (Lambda)Real user browsersAWS health check agents
Runs whenAlways, on scheduleOnly when users are activeAlways, on schedule
Scripting supportYes — Node.js or PythonNo — passive collectionNo — HTTP/HTTPS/TCP only
Browser testingYes (Puppeteer or Selenium)Yes (real browsers)No
Screenshots & artifactsYes, stored in S3NoNo
Best forFlow validation, API checks, SLA evidenceReal user experience, device and location dataBasic endpoint availability, DNS failover
Cost modelPer canary runPer 100K RUM eventsPer health check plus DNS queries

Route 53 health checks are the cheapest option for simple availability and integrate directly with DNS failover. CloudWatch Synthetics is right when you need to validate a multi-step flow or capture debugging artifacts. RUM gives you the real user picture that neither synthetic tool can provide. Most production applications benefit from having all three.

Core components of a canary

Every canary you create in CloudWatch Synthetics has these parts:

  • Script — a Node.js or Python file that defines what to test. It imports the synthetics module, which provides HTTP helpers and browser control methods.

  • Runtime — the managed execution environment AWS provides. It includes the synthetics library, an optional headless browser, and the Lambda runtime. Always use a currently supported runtime version; AWS deprecates old ones over time, and the console shows which are available.

  • Schedule — a rate expression such as rate(5 minutes) or a cron expression that controls how often the canary runs.

  • S3 bucket — where CloudWatch stores screenshots, HAR files, and logs from each run. Apply a lifecycle policy to this bucket from day one.

  • IAM execution role — the role the Lambda assumes. It needs permission to write to S3, publish to CloudWatch, and access any AWS resources your test touches.

  • VPC config (optional) — if your application runs inside a private VPC, configure the canary to run in the same VPC so it can reach internal endpoints.

Never put credentials in a canary script

Canary scripts are uploaded to S3 and visible to anyone with the right IAM permissions. If you hardcode a real username, password, or API key, it is effectively stored in plain text. Instead, store test credentials in AWS Secrets Manager and retrieve them inside the script at runtime using the SDK. The IAM role on the canary should have permission to read only the specific secret it needs.

Metrics, alarms, logs, screenshots, and artifacts

After each run, CloudWatch Synthetics automatically publishes metrics to the CloudWatchSynthetics namespace:

  • SuccessPercent — percentage of runs that passed. This is the primary metric to alarm on.

  • Duration — how long each step took. Useful for catching latency regressions before they become user-visible.

  • Failed — count of failed runs in the evaluation window.

Screenshots and HAR files from each run are saved to your S3 bucket and viewable in the CloudWatch Synthetics console. Use them to see exactly where a UI flow broke and what the page looked like at the moment of failure.

Display canary status alongside your other service health indicators using a

CloudWatch Dashboard

.

Quick start workflow

Here is a minimal Node.js canary that checks an API health endpoint and validates the response body, not just the status code:

const synthetics = require('Synthetics');
const log = require('SyntheticsLogger');

exports.handler = async () => {
  await synthetics.executeHttpStep(
    'Verify /health endpoint',
    {
      hostname: 'api.example.com',
      method: 'GET',
      path: '/health',
      port: 443,
      protocol: 'https:',
    },
    async (res) => new Promise((resolve, reject) => {
      let body = '';
      res.on('data', (chunk) => { body += chunk; });
      res.on('end', () => {
        if (res.statusCode !== 200) return reject(`Got ${res.statusCode}`);
        const data = JSON.parse(body);
        if (data.status !== 'ok') return reject(`Status: ${data.status}`);
        log.info('Health check passed');
        resolve();
      });
    })
  );
};

This checks more than a basic 200 response. It also parses the body and verifies that the status field equals ok. A server can return 200 with an error payload; this canary catches that case too.

Once your script is ready, deploy and start the canary. Replace the runtime version with the current supported version shown in the AWS console or documentation, as runtime versions are updated periodically.

# Zip and upload your script
zip canary.zip canary.js
aws s3 cp canary.zip s3://my-canary-bucket/scripts/

# Create the canary running every 5 minutes
aws synthetics create-canary \
  --name api-health-check \
  --code S3Bucket=my-canary-bucket,S3Key=scripts/canary.zip,Handler=canary.handler \
  --artifact-s3-location s3://my-canary-bucket/results/ \
  --execution-role-arn arn:aws:iam::123456789012:role/SyntheticsRole \
  --schedule Expression='rate(5 minutes)' \
  --runtime-version syn-nodejs-puppeteer-X.X

aws synthetics start-canary --name api-health-check

# Alarm on SuccessPercent — treat missing data as a failure
aws cloudwatch put-metric-alarm \
  --alarm-name "Canary-ApiHealthCheck-Failed" \
  --namespace CloudWatchSynthetics \
  --metric-name SuccessPercent \
  --dimensions Name=CanaryName,Value=api-health-check \
  --statistic Average \
  --period 300 \
  --threshold 100 \
  --comparison-operator LessThanThreshold \
  --evaluation-periods 1 \
  --treat-missing-data breaching \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:production-alerts

Example use cases

  • E-commerce checkout — a browser canary that navigates the product page, adds an item to the cart, and reaches the payment page without JavaScript errors.

  • SaaS login flow — an HTTP canary that submits credentials to your auth API and verifies the token response structure is intact.

  • Internal microservice health — canaries deployed inside a VPC that check internal service endpoints Route 53 health checks cannot reach.

  • Third-party dependency — a canary that calls an external payment or mapping API and fires an alarm if latency spikes or the response shape changes.

  • Regional failover validation — identical canaries in us-east-1 and eu-west-1 confirming that

    Route 53 failover routing

    directs traffic to a healthy region after a simulated failure.

  • EKS workload readiness — a canary that pings a service exposed through an ingress, complementing EKS monitoring with an external availability check.

Common beginner mistakes

  1. Only checking for HTTP 200. A page can return 200 with a blank body or an error message in the HTML. Write canaries that validate content: check that a specific element is present or the API response has the expected shape.

  2. Not setting treat-missing-data on the alarm. If the canary fails to run, the metric has no data and the alarm defaults to OK. Set treat-missing-data breaching on every canary alarm.

  3. Running canaries too infrequently. A canary running every 30 minutes can miss a 20-minute outage entirely. For critical paths, run every 1 to 5 minutes and balance the detection window against cost.

  4. Not setting an S3 lifecycle policy. Every run stores screenshots and HAR files. Without a lifecycle rule, these accumulate indefinitely. Apply an S3 lifecycle policy to expire canary artifacts after 30 to 90 days.

  5. Skipping VPC config for private services. A canary running in the default public context cannot reach endpoints inside a private VPC. If your app runs on private subnets, configure the canary VPC settings to match.

Cost and retention considerations

CloudWatch Synthetics charges per canary run. The first 100 runs per month are included in the free tier. After that, you pay a small per-run fee. Check the current AWS CloudWatch pricing page, as rates are updated periodically.

  • A canary running every 5 minutes makes roughly 8,640 runs per month, typically a few dollars per canary at standard rates.

  • Browser-based canaries take longer to execute than HTTP-only canaries and cost slightly more per run because Lambda charges by duration.

  • Artifacts in S3 accumulate at the rate of your run frequency. Set a lifecycle policy on the results bucket from day one.

  • Canary Lambda execution time also contributes to Lambda pricing, though the amounts are typically negligible for short-running checks.

Frequently asked questions

What is synthetic monitoring?

Synthetic monitoring runs scripted, simulated interactions against your app on a fixed schedule, even when no real users are active. It checks availability, measures latency, and verifies flows like login or checkout, alerting you the moment something breaks.

What is a CloudWatch canary?

A CloudWatch canary is a scheduled script managed by CloudWatch Synthetics. It runs on AWS Lambda, makes requests to your app via HTTP or headless browser, and publishes pass/fail metrics back to CloudWatch. If the canary fails, it triggers a CloudWatch alarm.

Does CloudWatch Synthetics use Lambda?

Yes. Each canary runs as a Lambda function under the hood. AWS manages the infrastructure. You supply the script and schedule, and CloudWatch Synthetics handles provisioning, execution, and storing results in S3.

How often should a canary run?

For critical paths like login or checkout, every 1 to 5 minutes is common. For less critical endpoints, every 15 to 30 minutes is often enough. The right cadence depends on how quickly you need to detect and respond to an outage.

How much does CloudWatch Synthetics cost?

CloudWatch Synthetics charges per canary run. As of 2026, the first 100 canary runs per month are free, then you pay a small per-run fee. A canary running every 5 minutes makes around 8,640 runs per month, typically a few dollars per canary. Check the current CloudWatch pricing page for exact rates.

What is the difference between synthetic monitoring and RUM?

Synthetic monitoring uses scripted bots that run on a schedule regardless of traffic. RUM (Real-User Monitoring) collects data from actual user browsers. Synthetics catches outages proactively; RUM shows the real experience across diverse devices and locations. Most teams use both.

Last verified: 3 May 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.