01 What they are for #
Everything else in APM is passive: it tells you about traffic that already happened. That leaves two gaps. At 3 a.m. there may be no traffic to observe, and some failures — a login that returns 200 with an empty token, a checkout that succeeds but writes nothing — look perfectly healthy from the outside.
A synthetic scenario is an active check: a scripted sequence of HTTP steps with assertions, executed by the appliance on a fixed interval. It fails loudly whether or not anyone is using the system.
02 Anatomy of a scenario #
- Steps
- Up to 20 HTTP requests executed in order. Each has a name, method, URL, optional headers and body, assertions, and extractions. Execution stops at the first failing step — there is no point asserting on a checkout when login already failed.
- Variables
- Key/value pairs available to every step as
in URLs, headers and bodies. - Assertions
- What must be true for a step to pass.
- Extractions
- Values pulled out of a response and stored as variables for later steps — how a session token flows from login to checkout.
- Check interval
- 15 seconds to 24 hours.
- Timeout
- 1 to 120 seconds per step.
- Retries
- 0 to 5. A retry runs the whole scenario again before recording a failure, which suppresses single-packet-loss noise.
- Verify TLS
- Turn off only for internal endpoints with self-signed certificates.
03 Assertions #
| Type | Operators | Example |
|---|---|---|
status_code | eq, neq, lt, lte, gt, gte | status_code eq 200 |
latency_ms | lt, lte, gt, gte, eq, neq | latency_ms lt 2000 |
body_contains | substring match | body contains Order confirmed |
json_path | exists, eq, neq, lt, lte, gt, gte, contains | user.roles[0].name eq admin |
JSON paths use dot and bracket notation — data.items[0].id. Numeric comparisons are
applied when both sides look numeric, so json_path total gt 0 behaves as you would expect.
A login endpoint returning 200 with {"token": null} is broken. status_code eq 200 passes; json_path token exists catches it. The whole value of synthetics is asserting the thing that actually matters.
04 A worked example #
A three-step checkout journey. Step 1 authenticates and extracts a token, step 2 uses it, step 3 checks the result reflects the change.
| # | Step | Assertions | Extracts |
|---|---|---|---|
| 1 | POST /api/auth/login with test credentials | status_code eq 200 json_path access_token exists | token ← json access_token |
| 2 | POST /api/cart/items, header Authorization: Bearer | status_code eq 201 latency_ms lt 2000 | cart_id ← json id |
| 3 | GET /api/cart/ | status_code eq 200 json_path items[0].sku eq TEST-SKU | — |
Scenarios run on their interval forever. Point them at a purpose-built account and test data, never at a real customer record, and make sure a scenario that creates something also cleans it up or writes somewhere disposable.
05 Running and reading results #
Run now executes immediately and returns full step-level detail — status code, latency, every assertion with pass/fail and the reason, and a snippet of the response body. Use it while authoring; it is far faster than waiting for the next scheduled tick.
Scheduled runs record: overall status (up/down), total duration, steps passed of steps total, which step failed and why. History is kept for 90 days, and the list shows uptime percentage, run count and average duration over the selected window.
Scenarios run from the appliance, so they see your network the way the appliance does. That is right for internal services, and it means a scenario against a public endpoint is not measuring what a customer in another region experiences.
06 Alerting and scheduling #
A scenario that transitions to down raises an alert on its configured channels, and clears when it passes again. Only one appliance worker executes each tick, so a multi-worker deployment does not multiply your synthetic traffic.
Choose the interval by how fast you need to know: 60 seconds for revenue-critical journeys, 5 to 15 minutes for everything else. Every scenario is real traffic against your own systems — a 15-second interval on a heavy flow is a load test you did not mean to write.