Caching and Performance Engineering · Performance and Scalability

Measuring Performance: Percentiles, Profiling and Load Tests

Know what 'fast' means and find where time goes.

Create a free account to save this page, take notes and track your progress. Sign in

Define performance goals as percentiles under load ("p99 < 300 ms at 2,000 RPS"), not averages. Measure in production with RED metrics and real-user monitoring, find hotspots with profilers (CPU, allocation, async) and traces, and verify capacity with load tests that model real traffic (k6, Gatling, Locust). Change one thing at a time and re-measure.

// k6 load test: ramp to 2,000 RPS, fail if p99 >= 300 ms or errors >= 1%
import http from "k6/http";
export const options = {
  scenarios: { ramp: { executor: "ramping-arrival-rate", startRate: 100, timeUnit: "1s",
    preAllocatedVUs: 500, stages: [{ target: 2000, duration: "10m" }, { target: 2000, duration: "20m" }] } },
  thresholds: { http_req_duration: ["p(99)<300"], http_req_failed: ["rate<0.01"] },
};
export default () => http.get("https://staging.example.com/api/products?limit=20");

Common pitfalls

  • Optimizing by intuition.
  • Load tests with unrealistic data or closed-model generators (coordinated omission).
  • Reporting averages that hide tail latency.

Key points

  • Goals as percentiles at a load
  • Profile and trace to find bottlenecks
  • Load test with realistic arrival rates

Further reading: Grafana k6 documentation

Practice questions

Why do open-model (arrival-rate) load tests matter?

Answer

Closed models wait for responses before sending more, so slowdowns reduce load and hide latency (coordinated omission); arrival-rate tests keep sending at the target rate like real users.

What's the first step when an endpoint is slow?

Answer

Measure: check traces/profiles to see where time goes (often database queries or downstream calls) before changing code.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?