SRE / Reliability Engineering Fundamentals · Module 02 of 12

SLIs: measure the user journey

Translate user expectations into service level indicators based on good events, valid events, latency, correctness and other observable outcomes instead of infrastructure convenience metrics.

Running case · checkout service

Carry the same user journey forward: customer → edge/API → checkout → payment. Reuse prior SLI/SLO, alert, incident and recovery decisions where relevant so this module adds evidence to one reliability system rather than starting from zero.

Learning objectives

By the end of this module, you should be able to:

  • Define an SLI as a quantitative measure of service behaviour.
  • Design request-based and time-based SLIs using good events divided by valid events.
  • Choose measurement points that approximate the user experience and document their limitations.

Start from a critical user journey

An SLI should represent whether an important user interaction succeeded, not simply whether a component was alive. Examples include successful checkout requests, timely search results or fresh data delivery.

Choose a small number of indicators that matter to users and that can be measured consistently.

Good events over valid events

Many request-based SLIs can be expressed as good events divided by valid events. “Good” must be explicit: correct status, bounded latency, valid content or another testable condition.

The denominator also matters. Health probes, bots or requests outside the supported contract may need to be excluded so the indicator measures the intended population.

Measurement location creates bias

An edge proxy, application, synthetic probe and client telemetry observe different parts of the user journey. Document where the SLI is measured and what failures it cannot see.

Prefer the closest practical approximation to user experience, then complement it when blind spots are important.

  • availability or success
  • latency
  • correctness or freshness
  • throughput where it represents user demand
  • durability for stored data

HTTP status policy is part of the SLI contract

Do not use a blanket status < 500 rule without documenting what it means. Some 4xx responses represent invalid or out-of-contract requests and may be excluded from the valid-event denominator; they should still be monitored separately.

For an otherwise valid user request, server-side admission control such as 429 or load shedding such as 503 is a user-visible inability to complete the journey and normally counts as bad for an availability SLI unless the service contract explicitly defines a different population.

Latency and freshness need distribution-aware SLIs

Average latency can hide a harmed tail. For interactive services, define good events using a latency threshold or inspect percentiles derived from an aggregatable histogram.

Not every service is request/response. A batch or data-product SLI can measure the proportion of expected jobs completed before a deadline, or the proportion of observations whose data age stays below a freshness threshold.

Worked example

Request success SLI

SLI = good requests / valid requests
    = 9,950 / 10,000
    = 99.5%
  • The numerator and denominator are both event counts for the same population.
  • If 5xx responses are failures but client-cancelled requests are excluded, document that policy.
Core lab · account-free

Lab 02 — Compute request SLIs from raw events

Goal: Calculate availability and latency-goodness from a small request dataset.

Before you start

  • No cloud account required.
  • Core lab uses bash/Python 3 and local files only.
  • Running case study: use the same checkout journey throughout the course unless the lab explicitly says otherwise.
STEP 1

Create request evidence

cat > /tmp/requests.csv <<'EOF'
status,latency_ms,valid
200,110,yes
200,780,yes
400,40,no
429,35,yes
503,20,yes
200,140,yes
EOF
STEP 2

Calculate the supported population

python3 - <<'PY2'
import csv
rows=list(csv.DictReader(open('/tmp/requests.csv')))
valid=[r for r in rows if r['valid']=='yes']
good=[r for r in valid if r['status']=='200' and int(r['latency_ms']) <= 300]
print('valid_events',len(valid))
print('good_events',len(good))
print('good_ratio',f'{len(good)/len(valid):.3f}')
print('bad_by_policy',[(r['status'],r['latency_ms']) for r in valid if r not in good])
PY2
STEP 3

Document the SLI contract

Write the contract explicitly: which requests are valid, which status/latency combinations are good, where the measurement is taken, and why valid 429/503 responses are treated as bad user outcomes in this checkout example.

Verify

  • Only user requests are in the denominator.
  • Availability and latency-goodness use explicit, different good-event definitions.

Expected outcome

  • A reproducible SLI calculation and a short measurement-contract note.

Diagnose / troubleshoot

  • If your denominator changes between indicators, document why.
  • If you use averages for latency, reconsider whether a threshold-based good-event SLI better matches the user expectation.
Real-world connection

A useful SLI is both technically computable and semantically tied to what users experience.

Real-tool practicum · optional but recommended

Optional practicum — query a real Prometheus SLI

Start the local SRE lab and query request/error counters from Prometheus.

Prerequisites

  • Docker/Compose available.
  • Download/extract the SRE Lab Pack or run from the Academy release source tree.

Resources created

  • Local demo HTTP service on port 8000 and Prometheus on port 9090.

Cost / risk

  • Local CPU/RAM only; the lab generates synthetic requests including deliberate 500/503 outcomes.
TOOL 1
./ops/setup-sre-local-lab.sh
TOOL 2
for p in ok ok slow fail shed; do curl -s -o /dev/null http://127.0.0.1:8000/$p || true; done
TOOL 3
curl -fsS http://127.0.0.1:9090/api/v1/query --get --data-urlencode 'query=1 - sre_demo:error_ratio:1m'
TOOL 4
curl -fsS http://127.0.0.1:9090/api/v1/query --get --data-urlencode 'query=histogram_quantile(0.95, sum by (le) (rate(sre_demo_request_duration_seconds_bucket{outcome=~"ok|slow"}[1m])))'

Verify

  • The first Prometheus query is a good/valid ratio rather than request rate.
  • The histogram query returns a p95 latency estimate for successful/slow responses.

Cleanup

  • ./ops/cleanup-sre-local-lab.sh

Warnings

  • Run only against the disposable local demo service.
  • Interpret the good/valid ratio according to the documented request contract; do not equate request rate with an SLI.
Avoid these traps

Common mistakes

  • Using CPU utilization as the primary user-facing availability SLI.
  • Leaving the denominator undefined.
  • Measuring only inside the service when edge or client failures materially affect users.
Knowledge check

Can you connect the reliability objective to an engineering decision?

Three concept checks plus one scenario check.

1What is an SLI?

A quantitative measure of a defined aspect of service behaviour, such as the ratio of good requests to valid requests.

2Why must the denominator of an SLI be documented?

Because the population of valid events determines what user experience the indicator represents.

3Why can a successful response still be “bad” for a latency SLI?

Because the SLI can define good events as successful responses that also complete within the user-relevant latency threshold.

4Scenario: the application reports 100% success, but an edge proxy is dropping 8% of requests before they reach it. What does this reveal?

The application-side SLI has a measurement blind spot; an edge or client-side signal is needed to represent the affected user journey.

My Learning

Record your progress for this module.

Progress is saved in this browser immediately. When you sign in to My Learning, it can also sync across devices.

Not started

Attempt the core lab and knowledge checks before marking the module complete.