Как посчитать Apdex score в SQL

Закрепи формулу apdex score в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать apdex score в Telegram

Зачем Apdex

P95 latency 500ms — это много или мало? Зависит от endpoint. Apdex (Application Performance Index) — единая metric, нормирующая UX к threshold T. Apdex 0.9+ — excellent. 0.7-0.85 — fair. Меньше 0.7 — frustrating.

Формула

Apdex = (satisfied + tolerating/2) / total
  • satisfied = requests under T
  • tolerating = T to 4T
  • frustrated = above 4T

Range [0, 1]. 1 = все юзеры satisfied.

Apdex в SQL

WITH config AS (
    SELECT 500 AS t_ms  -- threshold T IN milliseconds
)
SELECT
    COUNT(*) AS total,
    COUNT(*) FILTER (WHERE latency_ms <= (SELECT t_ms FROM config)) AS satisfied,
    COUNT(*) FILTER (WHERE latency_ms > (SELECT t_ms FROM config) AND latency_ms <= 4 * (SELECT t_ms FROM config)) AS tolerating,
    COUNT(*) FILTER (WHERE latency_ms > 4 * (SELECT t_ms FROM config)) AS frustrated,
    (COUNT(*) FILTER (WHERE latency_ms <= (SELECT t_ms FROM config))
     + COUNT(*) FILTER (WHERE latency_ms > (SELECT t_ms FROM config)
                          AND latency_ms <= 4 * (SELECT t_ms FROM config)) / 2.0
    ) / NULLIF(COUNT(*), 0) AS apdex
FROM api_requests
WHERE request_timestamp >= NOW() - INTERVAL '1 hour';

Apdex 0.95 — отлично. 0.85 — норма. 0.7-0.85 — UX issues.

По endpoint

SELECT
    endpoint,
    COUNT(*) AS requests,
    SUM(CASE WHEN latency_ms <= 500 THEN 1
             WHEN latency_ms <= 2000 THEN 0.5
             ELSE 0
        END)::NUMERIC / NULLIF(COUNT(*), 0) AS apdex
FROM api_requests
WHERE request_timestamp >= NOW() - INTERVAL '1 hour'
GROUP BY endpoint
HAVING COUNT(*) >= 100
ORDER BY apdex ASC
LIMIT 10;

Endpoint с самым низким Apdex — приоритет оптимизации.

Закрепи формулу apdex score в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать apdex score в Telegram

Threshold T

T выбирают по user expectations. Common targets:

  • Web pages: T = 500ms, frustrated above 2s
  • API: T = 100ms, frustrated above 400ms
  • Database query: T = 50ms
SELECT
    endpoint,
    CASE
        WHEN endpoint LIKE '/api/%' THEN 100
        WHEN endpoint LIKE '/web/%' THEN 500
        ELSE 1000
    END AS t_ms
FROM endpoint_config;

Частые ошибки

Ошибка 1. T не set per endpoint. Один T для всех endpoints — UX-неаккуратно. Customize.

Ошибка 2. Включать errors как frustrated. 5xx errors — separately. Apdex про latency, не reliability.

Ошибка 3. Single Apdex для team. Per-service Apdex. Aggregate hides issues.

Ошибка 4. Threshold T меняется. Compare историчные Apdex on consistent T.

Ошибка 5. Apdex как sole metric. Combine с error rate, throughput. Apdex про speed.

Связанные темы

FAQ

Какой Apdex хороший?

0.94-1.0 — excellent. 0.85-0.94 — good. 0.7-0.85 — fair. Меньше 0.7 — bad.

T для checkout?

User-facing critical: 1s. Backend: 200-500ms.

Apdex deprecated?

Some teams перешли на raw percentiles. Apdex still useful для one-number health check.

Apdex + errors?

Errors обычно treated as frustrated в strict definition. Soft definition — отдельный metric.

Calibrate T?

Survey users: «какая latency приемлема?» Median ответов — T.