Datadog Synthetic Monitoring: Browser Tests, API Tests, and Global Alerting
Synthetic monitoring runs scripted tests against your application on a schedule — whether or not any real user is currently visiting. It catches downtime, broken flows, and performance regressions before your users do. Datadog's synthetic monitoring combines API checks, browser automation, and a global network of test locations into a unified observability layer. This guide covers everything from your first API test to a fully configured synthetic suite.
The Two Test Types
Datadog Synthetic has two distinct test types, and understanding the difference determines which to use for a given use case.
API tests send an HTTP request (or a chain of them) and assert on the response. They start in milliseconds, run globally at high frequency, and are ideal for:
- Uptime checks on critical endpoints
- Verifying response bodies, headers, and status codes
- SSL certificate expiry monitoring
- DNS resolution checks
- TCP/UDP port checks
Browser tests launch a real Chromium browser, navigate your application, interact with it (click, fill forms, scroll), and assert on what the user sees. They take 30–120 seconds to complete and are ideal for:
- Login flows
- Checkout flows
- Multi-step user journeys
- JavaScript-heavy SPAs where the API response alone does not reflect what the user experiences
The rule of thumb: if the thing you want to monitor is a user journey, use a browser test. If it is an endpoint's availability or correctness, use an API test.
Creating Your First API Test
Navigate to Synthetic Monitoring → New Test → API Test.
Simple HTTP Check
The simplest case — verify your homepage returns 200:
- URL:
https://app.example.com - Method: GET
- Assertions:
- Response status code
is200 - Response time
is less than2000ms - Response body
contains"Welcome"
- Response status code
Test locations: select 3–5 geographically distributed locations (US East, EU West, Asia Pacific). This catches region-specific DNS or CDN issues that a single-location check would miss.
Advanced request configuration lets you add headers (e.g., Authorization: Bearer {{synthetic_token}}), request body for POST requests, and follow redirects. Variables defined in the test can reference Datadog global variables — useful for credentials you do not want hardcoded in the test.
Assertions Reference
| Assertion type | Options |
|---|---|
| Status code | is, is not |
| Response time | is less than |
| Header | contains, does not contain, matches regex |
| Body | contains, does not contain, equals, matches regex, is valid JSON, has JSON path |
| Certificate | expires in more than N days |
For JSON APIs, use JSONPath assertions to check specific fields:
- JSONPath
$.user.statusequals"active" - JSONPath
$.items.length()is greater than0
Multistep API Tests
Single-request checks break down for workflows that require authentication or chained requests (e.g., create a resource, then fetch it, then delete it). Multistep API tests solve this.
Example: test order creation flow
Step 1 — Authenticate:
POST https://api.example.com/auth/token
Body: { "client_id": "{{CLIENT_ID}}", "client_secret": "{{CLIENT_SECRET}}" }
Extract variable: TOKEN from $.access_token
Assert: status 200Step 2 — Create order:
POST https://api.example.com/orders
Header: Authorization: Bearer {{TOKEN}}
Body: { "product_id": "prod_123", "quantity": 1 }
Extract variable: ORDER_ID from $.id
Assert: status 201
Assert: $.status equals "pending"Step 3 — Verify order exists:
GET https://api.example.com/orders/{{ORDER_ID}}
Header: Authorization: Bearer {{TOKEN}}
Assert: status 200
Assert: $.product_id equals "prod_123"Step 4 — Cancel order:
DELETE https://api.example.com/orders/{{ORDER_ID}}
Header: Authorization: Bearer {{TOKEN}}
Assert: status 204Each step's extracted variables are available to subsequent steps. This lets you test stateful workflows end-to-end without mocking.
Variables extracted via JSONPath, regex, or header parsing can also be used in later assertions, enabling response chaining where the exact behavior of your API — not just a stubbed version — gets tested.
Browser Tests
Recording vs. Code
Datadog's browser test recorder is a Chrome extension that captures your interactions and generates a test automatically. It works well for initial scaffolding; real-world tests usually need manual editing afterward.
For a login flow, the recorder generates steps like:
- Go to
https://app.example.com/login - Click on
#email - Type
{{USERNAME}} - Click on
#password - Type
{{PASSWORD}} - Click on
button[type="submit"] - Assert URL contains
/dashboard - Assert element
.user-greetingcontainsHello
The key addition after recording: replace hardcoded credentials with Datadog global variables ({{USERNAME}}, {{PASSWORD}}). Store credentials in Settings → Global Variables with the sensitive flag set — they are encrypted at rest and never appear in test logs.
Robust Selectors
The recorder uses whatever CSS selector or XPath it finds. These break easily when developers change class names. Make your tests resilient by preferring:
data-testidattributes — adddata-testid="login-button"to your markup and target[data-testid="login-button"]in tests. These survive CSS refactors.- Accessible roles — Datadog supports ARIA role selectors (
button[name="Sign in"]) - Text-based assertions — assert on visible text, not implementation details
Avoid: long auto-generated CSS selector chains like div.container > div:nth-child(2) > form > button.btn-primary. These are the first thing to break.
Custom JavaScript Steps
For complex interactions that the recorder cannot capture, add a Run JavaScript step:
// Dismiss a cookie banner if present
const banner = document.querySelector('#cookie-banner');
if (banner) {
banner.querySelector('button.accept').click();
}
return true;Browser tests execute in a sandboxed Chromium instance; the JavaScript step runs in that page's context. Return true to pass, throw an error or return falsy to fail.
Screenshots and Waterfalls
Every browser test step captures a screenshot. When a test fails, Datadog shows you exactly what the browser saw at the failing step — eliminating the "works on my machine" problem for UI bugs.
Browser tests also record a waterfall diagram of network requests, similar to Chrome DevTools. You can add performance assertions:
- First contentful paint
< 1500ms - DOM interactive
< 2000ms - Largest contentful paint
< 2500ms
These catch performance regressions in real browser rendering, not just server-side response time.
Global Test Locations
Datadog runs synthetic tests from 30+ managed locations worldwide. For public-facing services, always run from multiple regions:
- AWS us-east-1, us-west-2
- AWS eu-west-1, eu-central-1
- AWS ap-southeast-1, ap-northeast-1
This catches:
- CDN misconfigurations affecting specific regions
- DNS propagation issues
- Latency that only manifests at geographic distance
- Geo-restricted content failing when it should not
Private locations let you run synthetic tests inside your private network — VPCs, staging environments behind a VPN, internal APIs. Install the private location agent as a Docker container or Kubernetes deployment:
docker run -d --rm \
-e DATADOG_API_KEY=<API_KEY> \
-e DATADOG_PRIVATE_LOCATION_ID=<LOCATION_ID> \
datadog/synthetics-private-location-workerOnce running, the private location appears in your test's location list like any managed location. This closes the gap where your synthetics could check public endpoints while internal services went unmonitored.
Test Frequency and SLA Targets
Choose test frequency based on the acceptable detection window for a given failure:
| Endpoint criticality | Recommended interval |
|---|---|
| Revenue-critical (checkout, login) | 1 minute |
| Core product features | 5 minutes |
| Secondary features | 15–30 minutes |
| Background/internal APIs | 1 hour |
Browser tests are slower and more expensive — 15 or 30 minute intervals are typical for most flows, with 5 minutes reserved for checkout and login.
Datadog's SLO feature lets you define service level objectives based on synthetic test results:
- Navigate to SLOs → New SLO → Monitor-based
- Select your synthetic monitor
- Set target: 99.9% success over rolling 30 days
- Add error budget burn rate alerts
This gives you a quantified uptime commitment backed by actual test data, not just anecdotal observation.
Configuring Alerts
Monitor Configuration
Every synthetic test generates a monitor. Edit its notification settings:
- Alerting conditions: alert if the test fails from
at least 2 locationsforat least 2 minutes - This prevents false positives from transient single-location network blips
- For critical tests, lower to 1 location for 1 minute to maximize sensitivity
Notification channels:
- PagerDuty for immediate on-call escalation
- Slack for team visibility
- Email for stakeholder reporting
Message template variables let you include the failure reason, affected locations, and a direct link to the test result in your alert:
Synthetic test {{test.name}} FAILED
Location: {{location.name}}
Failure: {{failure.message}}
See trace: {{test.url}}Multi-location Logic
You can configure monitors to alert only when failures are detected from multiple locations simultaneously — filtering out single-region blips:
- Alert from
3 of 5 locationsfailing = the service is genuinely down globally - Alert from
1 of 5 locationsfailing = possible regional issue worth investigating but not paging
For tests covering user flows rather than raw uptime, consider longer evaluation windows (5 consecutive failures) to avoid alert fatigue from intermittent rendering issues.
CI/CD Integration
Synthetic tests running on a schedule catch production regressions. Running them in CI catches regressions before deploy. Datadog's datadog-ci tool triggers synthetic tests as a CI step and blocks the pipeline on failures:
npm install -g @datadog/datadog-ci
datadog-ci synthetics run-tests \
--apiKey $DD_API_KEY \
--appKey $DD_APP_KEY \
--public-id abc-def-123 \
--public-id xyz-uvw-456 \
--failOnCriticalErrors \
--tunnelThe --tunnel flag routes test traffic through a secure tunnel to your ephemeral CI environment, so you can test a staging deployment that is not publicly accessible without setting up a private location.
In GitHub Actions:
- name: Run Datadog Synthetics
run: |
npx @datadog/datadog-ci synthetics run-tests \
--config ./synthetics.config.json \
--tunnel
env:
DATADOG_API_KEY: ${{ secrets.DD_API_KEY }}
DATADOG_APP_KEY: ${{ secrets.DD_APP_KEY }}synthetics.config.json can override test variables per environment — using staging URLs and test credentials rather than production values.
Correlating Synthetics with APM
When APM tracing is enabled on your application and the x-datadog-trace-id header is present in synthetic requests (it is, by default), Datadog links each synthetic test run to the APM trace it generated.
This means: when a synthetic test fails with a slow response, you can click through from the test result directly to the distributed trace — seeing every database query, every downstream service call, every millisecond — without any manual correlation.
This connection is one of the most powerful aspects of keeping monitoring inside Datadog: test failure → trace → log line is a single navigation path, not a three-tool investigation.
Test Organization and Maintenance
As your synthetic suite grows, use tags to organize tests:
env:production,env:stagingteam:payments,team:onboardingcriticality:p0,criticality:p1
Tag-based filtering lets you run only a specific team's tests in CI, or only P0 tests as a post-deployment smoke check.
For browser tests, extract repeated sequences (like the login flow) into sub-tests and reference them from other tests. A sub-test is a reusable browser test step sequence — update the login sub-test once when your login UI changes and all 15 tests that depend on it are fixed automatically.
What Synthetics Does Not Replace
Synthetic monitoring excels at scheduled, scripted verification. It does not replace:
- Real user monitoring (RUM) — capturing actual user sessions, including device/browser variations and frustration signals (rage clicks, dead clicks)
- End-to-end test suites — thorough coverage of edge cases, error states, and data variations that scheduled synthetics would not hit at reasonable frequency
- Load testing — synthetics runs single-user flows, not concurrent load
A complete observability stack typically combines all three: synthetics for always-on uptime and journey verification, RUM for real-user experience data, and dedicated test tools for deep functional coverage.
Summary
A production-grade Datadog synthetic setup requires:
- API tests on every critical endpoint — status codes, response bodies, SSL certs
- Multistep API tests for authenticated workflows and chained operations
- Browser tests for key user journeys (login, checkout, core feature activation)
- Multi-region locations — minimum 3 for public services
- Private locations for internal APIs and staging environments
- CI integration so tests block deploys on failure
- SLOs backed by synthetic test data to quantify uptime commitments
- APM correlation so test failures trace directly to the responsible code
Start with API tests on your most critical endpoints. Add browser tests for your top 3 user journeys. The returns are immediate — you will catch the next production incident before a user files a support ticket.