---
title: "Throughput vs Latency: How to Present Results Stakeholders Actually Understand"
description: "Throughput vs latency for executives: tie k6 RPS to percentile stories—Little's Law intuition and SLO-minded stakeholder reporting."
publishDate: "2026-09-24"
draft: false
keyword: "throughput vs latency"
intent: "TOFU"
cta: "Explore how Performate simplifies k6 load testing—from imports to results—so your team ships performance confidence faster."
tags: ["k6","load-testing","api-performance","throughput","latency"]
---

Executives ask "how many requests per second?" while engineers guard `p99`—then both leave confused when RPS rises and UX worsens. **Throughput and latency tell different stories**; conflating them erodes trust in perf programs and leads to bad capacity bets.

[Little's Law](https://en.wikipedia.org/wiki/Little%27s_law) intuition: in steady state, average concurrency ≈ arrival rate × average response time. Higher RPS with fixed capacity often means longer queues—show both throughput **and** percentiles on the same slide with the **same** test duration and env footnote.

This guide maps metrics to audiences, gives a k6 tagging pattern for checkout-focused exports, and includes a decision table for the questions stakeholders actually ask in readouts.

## What to chart for whom

Different audiences need different cuts of the same k6 run—never one chart forced on everyone:

- **Leadership:** SLO pass/fail at **stated RPS**, `p95`/`p99` vs target, trend vs last release, one-line env fidelity caveat.
- **Product:** Journey-level latency (checkout, search submit)—not global service average hiding slow steps.
- **Engineering:** RPS achieved, errors by `route` tag, saturation signals from APM, failed checks.
- **Finance/capacity:** Max RPS meeting SLO with headroom %—not peak RPS alone.

Never present only `http_req_duration` avg—mean hides tail pain ([p95 vs p99](/en/blog/p95-vs-p99-latency)). Never present peak RPS without saying whether SLOs still passed at that rate.

### The footnote that saves your credibility

Every stakeholder slide needs: **RPS, duration, environment, synthetic data yes/no**. Missing footnotes cause "staging said 2k RPS" legends in production postmortems ([staging vs prod](/en/blog/staging-vs-production-load-tests)).

## k6: export-friendly tags

Segment checkout (or your revenue path) for product slides; keep `report:exec` tag for filtering exports from the same run engineering uses.

**Example (illustrative).** Steady ARR with route-specific thresholds.

**What this demonstrates:**

- `constant-arrival-rate` fixes business RPS—leadership number matches test config.
- Thresholds on `route:checkout` only—product slide not polluted by health checks.
- Tag `report:exec` filters Performate PDF sections for leadership template.
- Think time included—RPS honest vs machine-gun requests ([VU sanity](/en/blog/virtual-users-think-time-ai-sanity-checks)).

```javascript
import http from 'k6/http';
import { check, sleep } from 'k6';

const BASE = __ENV.API_BASE || 'https://staging.example.com';

export const options = {
  scenarios: {
    steady: {
      executor: 'constant-arrival-rate',
      rate: Number(__ENV.RPS || 50),
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 25,
      maxVUs: 100,
      tags: { report: 'exec' },
    },
  },
  thresholds: {
    'http_req_duration{route:checkout}': ['p(95)<800', 'p(99)<1200'],
    http_req_failed: ['rate<0.01'],
  },
};

export default function () {
  http.get(`${BASE}/catalog`, { tags: { route: 'browse' } });
  sleep(1);
  const res = http.post(`${BASE}/checkout`, '{}', {
    headers: { 'Content-Type': 'application/json' },
    tags: { route: 'checkout', report: 'exec' },
  });
  check(res, { ok: (r) => r.status < 500 });
  sleep(0.5);
}
```

**Patterns that work**

- **Two charts:** throughput (RPS achieved) + percentiles at that RPS—same run, same footer.
- **Before/after at same RPS** for release comparisons—"faster" claims require controlled RPS.
- **Link [performance budgets](/en/blog/performance-budget-frontend-api)** when UI latency is part of journey SLO.
- **Performate filter by `route:checkout`** before PDF export—product readout in one click.

**Anti-patterns to avoid**

- Bragging peak RPS from stress test where errors exceeded SLO—throughput without quality is noise.
- Mixing load and spike runs on one trend line—shapes differ ([stress vs load vs spike](/en/blog/stress-vs-load-vs-spike-testing)).
- Executive slide with only mean latency—tail users drive support tickets.
- Comparing this week's staging RPS to last month's production slide—env mismatch.

**Pro tip (example command):** percentile-focused summary for exec appendix.

```bash
k6 run stakeholder-run.js --summary-trend-stats="p(95),p(99),avg" --tag report=exec
```

**What this command demonstrates:** summary block pastes into appendix with both tail and mean—reviewers see you did not cherry-pick average only.

## Decision table: stakeholder question vs answer

| Stakeholder asks | Answer with | Do not answer with |
|:---|:---|:---|
| "Are we faster?" | `p95`/`p99` vs baseline at **same RPS** | Peak RPS from different test type |
| "Can we handle more users?" | Max RPS meeting SLO + headroom % | VU count without think time |
| "Did the release help?" | Same RPS before/after, compare percentiles | Different durations or envs |
| "Are we ready for launch?" | Load + spike pass/fail table with dates | Single staging smoke |
| "Why slow if RPS is fine?" | Little's Law queue story + saturation metrics | Blaming "the cloud" without data |

**Lead with SLO percentiles at stated RPS**—throughput is context, not the headline, unless the question is explicitly capacity headroom.

## Observability and reporting checklist

- [ ] One page: RPS chosen, duration, env fidelity note, synthetic data confirmation.
- [ ] Separate charts for throughput achieved and percentiles—same run ID.
- [ ] Link to [performance budgets](/en/blog/performance-budget-frontend-api) when UI involved in journey.
- [ ] Archive export with release SHA—week-over-week comparison in Performate.
- [ ] Product route tagged (`route:checkout`)—not only global `http_req_duration`.
- [ ] Spike vs load labeled if multiple runs in deck—do not merge test types.

## How Performate supports stakeholder reporting

Below is a **concrete workflow example** for exec-ready checkout reporting—adapt routes to your revenue path.

**Example: one run, two exports**

1. **Run** steady scenario at agreed RPS—5m minimum for stable percentiles. *Problem solved:* leadership number tied to real test config, not back-of-napkin.
2. **Filter** report by `route:checkout` and tag `report:exec`. *Problem solved:* product slide excludes unrelated routes from same run.
3. **Export** PDF with percentile trends + RPS footer auto-included. *Problem solved:* no manual spreadsheet transcription errors.
4. **Duplicate** slide template—RPS + p99 + pass/fail vs SLO doc. *Problem solved:* consistent readouts quarter over quarter.
5. **Archive** with release SHA beside engineering full export. *Problem solved:* audit trail when someone asks "which build was this?"
6. **Present** comparison view week over week at **same RPS**—not mixed shapes. *Problem solved:* "are we faster?" answered honestly.

That workflow maps directly to the `cta` in this post: simplify path from k6 run to stakeholder-ready evidence.

## Closing takeaway

Stakeholder-ready perf reports lead with **SLO percentiles at stated RPS**, not throughput bragging rights. Fix the RPS footnote, split charts, and tag revenue routes before the next exec readout.

Take your last k6 export, add RPS and env to slide one, and move peak throughput to appendix where it belongs.

[Try Performate free](https://performate.app) | [Guides](/guides) | [Book a demo](/demo)
