Apdex alerts
How to set up an Apdex alert in Maple: pick the target latency T, choose the score worth paging for, scope and tune the rule, and create the same rule over the API.
A p95 latency alert tells you that 5% of requests were slower than some number. It does not tell you whether that was 5 requests or 50,000, and it says nothing about the requests that failed outright.
Apdex answers a different question: of everything that hit this service in the last five minutes, what share of it was fast enough to keep a user happy?
The score in one line
Apdex compresses a latency distribution into a single number between 0 and 1: the share of requests that were fast enough to keep a user happy. You set one target time, T. Requests under T are satisfied and score a point, requests under 4T are tolerating and score half, and everything slower is frustrated and scores nothing. A request that failed is frustrated too, at any speed.
Counting failures as frustrated is what makes this worth alerting on. A dependency that starts failing 15% of requests in 40ms makes your p95 faster, so a latency alert stays quiet while Apdex falls from 0.97 to about 0.83.
What is Apdex? walks through the formula, a worked example, and where Apdex and latency percentiles disagree. The rest of this page is the Maple-specific part: picking T for a rule, and building it.
Choosing T for the rule
T is the whole rule. It sets the satisfied boundary directly and the frustrated boundary implicitly, since the tolerating band always ends at 4T. Move T from 500ms to 1s and you have also moved the frustrated line from 2s to 4s.
Pick T as the latency at which your users stop perceiving the response as immediate, per class of traffic:
Two ways to pick a T that tells you nothing. Setting T to your current p95 guarantees a score near 0.95 forever. Setting it so tight that a healthy week already reads 0.6 buries every threshold you might pick inside your normal noise.
To choose, open the service’s Apdex chart in Maple, set T, and check that a healthy week reads somewhere in the 0.9 to 1.0 band. That leaves the 0.8 line meaningful.
Choosing the threshold you defend
0.8 is a common convention. Set the threshold from where your service sits when it is healthy, and how far it has to fall before you would want to be woken up.
Setting up an Apdex alert in Maple
Maple computes Apdex over the entry-point spans of a service: server spans, consumer spans and trace roots. The service’s Apdex chart draws the same set of requests, so a rule you build here matches the chart.
1. Start from the Low Apdex score template
Open Alerts → New rule. Starting from a service page instead (Services → your service → Create Alert) pre-fills the scope.
The rule builder opens on Start with a template. Pick Low Apdex score and every field below is filled: signal Apdex, target 500ms, fires below 0.8, five-minute window. Nothing is locked afterwards.
2. Set the target, then the score you defend
Apdex target (ms) is your T: requests under it count as fully satisfied, and the frustrated line follows automatically at 4T. Then set Condition to < and Threshold to the score worth paging for, typically 0.8.
The panel also states the measurement boundary: built-in signals read entry-point spans only. A service that swallows failures on child spans and returns success from its entry point stays healthy here at any threshold. Use a Query or Raw SQL rule for that case.
<, threshold 0.8. (The decimal comma is the browser's locale, not a Maple setting.)3. Scope it
One T fits one class of traffic. If a rule covers many services or routes, set Group by to service.name or attr.http.route so each group is scored on its own and opens its own incident. Scope, grouping and the other fields shared by every signal are described in Alert rules.
4. Window, timing, destinations
Five minutes is the default window. Short windows on low-traffic services are noisy for Apdex in particular, because a handful of slow requests moves the ratio a long way. Keep Min samples at 50 or higher, and raise it on low-traffic services, so a service with 4 requests at 3am cannot post a score of 0.5 and page someone.
An Apdex rule skips windows with no requests, so a service that goes quiet overnight does not read as a score of 0. The other timing fields (Breaches to fire, Healthy to resolve, Renotify (min)) work as on every rule. See Evaluation timing.
Pick a Severity, attach your notification destinations, click Test rule to replay the rule over the past week, and save.
Creating the same rule over the API
Every field in the form is a field on the API. apdex_threshold_ms is T in milliseconds. It defaults to 500 when omitted.
curl -X POST https://api.maple.dev/v2/alerts/rules \
-H "Authorization: Bearer maple_ak_…" \
-H "Content-Type: application/json" \
-d '{
"name": "Checkout Apdex below 0.8",
"signal_type": "apdex",
"apdex_threshold_ms": 500,
"comparator": "lt",
"threshold": 0.8,
"window_minutes": 5,
"service_names": ["checkout"],
"environments": ["production"],
"severity": "critical",
"minimum_sample_count": 50,
"consecutive_breaches_required": 2,
"destination_ids": ["dest_oybbpTBhtSFGShMjjLiCrh"]
}'
To see what the rule would have done over a past range before it can wake anyone, send the same object as rule to POST /v2/alerts/rules/preview, with start_time and end_time:
{
"rule": {
"name": "Checkout Apdex below 0.8",
"signal_type": "apdex",
"apdex_threshold_ms": 500,
"comparator": "lt",
"threshold": 0.8,
"window_minutes": 5,
"service_names": ["checkout"],
"severity": "critical",
"destination_ids": ["dest_oybbpTBhtSFGShMjjLiCrh"]
},
"start_time": "2026-07-08T00:00:00.000Z",
"end_time": "2026-07-15T00:00:00.000Z"
}
See Alert rules and the API reference for the full schema.
Or hand it to an agent
You can also create the rule from an AI assistant. Connect Maple’s MCP server to any MCP client, then ask for the rule in plain language:
Create an Apdex alert on the checkout service. Target 500ms, page me when the score drops below 0.8, and send it to the on-call Slack channel.
The agent builds the same rule you would build by hand. It cannot save an Apdex rule without a target, and it only sees your own organization’s data.
After the rule exists, you can ask which of your Apdex rules would never fire, or why one paged last night. The agent reads the rule’s checks and incidents to answer.
Known limitations
- Apdex is computed on sampled spans. Under uniform sampling the score stays representative. A sampler that keeps slow or failed traces preferentially, without reporting its sampling weight, drags the score down. See Sampling and throughput.
- One T per rule. A service whose
/healthzand/reports/exportshare a rule is being measured against a target that fits neither. Group byattr.http.route, or write separate rules. - The score hides magnitude. It counts frustrated requests without weighting how frustrated they were. Pair it with a p99 rule.
The What is Apdex? guide covers the formula, a worked example, what counts as a good score, and how Apdex compares to p95 and p99.