Skip to main content

Load Testing for Media Streaming Performance

Load Testing for Media Streaming Performance

Key Takeaways

  • Load testing a streaming platform means replaying what players request (playlists, segments, login and entitlement calls), not decoding video.
  • Model a live event as a wave of arrivals before the start, not as a flat number of users.
  • Test the CDN path and the origin separately, because they fail in different ways.

An earlier version of this post described a case study of an unnamed platform with 600,000 simulated viewers and exact before and after latency figures. None of it could be verified, so it has been removed. This version is a how-to, and every number in it is either arithmetic you can redo or labelled as an example.

How do you load test a media streaming platform?

You script the requests a video player makes, run many of them at once from several regions, and watch response times and errors at the CDN, the origin and the backend services around them. The load test cannot see pictures or measure rebuffering on a screen. What it can show is whether segments arrive fast enough, and whether login, entitlement and API calls hold up while everyone joins at the same moment.

What does a streaming load test exercise?

With HTTP Live Streaming (HLS), a player fetches a master playlist, picks a rendition, then keeps requesting a media playlist and the segments it lists. With MPEG-DASH it does the same with a manifest. Around that sit calls a test must include: sign-in, entitlement checks, DRM license requests if you use them, and your own APIs for catalogue and playback state. Every one of those can be the bottleneck on launch day, and the segments are usually the least of your worries because the CDN serves them.

How many requests does a live audience create?

A rule in the HLS specification gives you the arithmetic. RFC 8216, section 6.3.4, says a client must wait at least one target duration between reloads of a live media playlist (rfc-editor.org, read 2026-10-23). Assume a target duration of 6 seconds and a segment length of 6 seconds, as an example:

ViewersPlaylist requests per second (at most)Segment requests per second (about)Egress at 5 Mbit/s per viewer
10,0001,6671,66750 Gbit/s
100,00016,66716,667500 Gbit/s

Each viewer sends about one playlist and one segment request per 6 seconds, so divide viewers by 6. Egress is viewers times bitrate. These numbers describe the CDN edge. The origin only sees cache misses, so the number worth testing there is how it behaves when the cache is cold, for example at the start of an event or after a purge.

How do you model a live-event audience?

Live audiences arrive in a wave in the minutes before the start, then hold. In k6 that is an arrival-rate scenario: the ramping-arrival-rate executor starts iterations at a set rate regardless of how quickly the system responds (grafana.com/docs/k6, read 2026-10-23), which is how real viewers behave. A fixed pool of virtual users slows down when the system slows, and so hides the overload.

A viewer holds a virtual user for the whole session. By Little’s Law, concurrent users equal arrival rate times session length: 50 new viewers per second with a 30-second session needs about 1,500 virtual users. Size preAllocatedVUs and maxVUs from that.

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

export const options = {
  scenarios: {
    join_wave: {
      executor: 'ramping-arrival-rate',
      startRate: 5,
      timeUnit: '1s',
      stages: [
        { target: 50, duration: '5m' },  // viewers joining per second
        { target: 50, duration: '10m' }, // hold the peak
      ],
      preAllocatedVUs: 1500,
      maxVUs: 2000,
    },
  },
  thresholds: {
    http_req_failed: ['rate<0.01'],
    'http_req_duration{kind:segment}': ['p(95)<2000'], // example limit, set your own
  },
};

const BASE = 'https://cdn.example.com/live/event1'; // your own stream

export default function () {
  const playlist = http.get(`${BASE}/720p/index.m3u8`, { tags: { kind: 'playlist' } });
  check(playlist, { 'playlist 200': (r) => r.status === 200 });

  const segments = playlist.body.split('\n').filter((l) => l && !l.startsWith('#'));
  for (const seg of segments.slice(-5)) {
    const res = http.get(`${BASE}/720p/${seg}`, { tags: { kind: 'segment' } });
    check(res, { 'segment 200': (r) => r.status === 200 });
    sleep(6); // one segment duration
  }
}

This is a sketch: it plays one rendition and ignores adaptive bitrate switching, ads and sign-in. Add the sign-in and entitlement calls before the playlist, and a mix of renditions that matches your real audience. The guide to simulating realistic user behavior covers modelling that mix, and running k6 at scale covers what happens when one machine cannot generate the load.

How do you test the CDN and the origin?

Run two kinds of test. Against the CDN path, with warm caches, you learn whether the edge serves segments quickly from your target regions. Against the origin, with cache-busting or a cold start, you learn how much traffic the origin takes when many viewers ask for the same new segment at once. Check your CDN provider’s policy on load tests first, because some providers want notice before large tests. Never point a test at a stream or domain you do not own.

Test from the regions where your audience is. Latency from one cloud region says little about a viewer on another continent, and network latency affects the accuracy of cloud tests in its own right.

How do you read the results?

  • Segment response time against segment length. A 6-second segment must arrive well before it is needed. If the p95 for segment requests climbs toward a few seconds, players will drain their buffer and stall. Use percentiles, not averages.
  • Error rate by request type. A rise in 5xx on playlists points at the origin or the packager. A rise on sign-in points at your own backend.
  • Where it breaks. Add load in steps and note the viewer count at which latency bends upward.
  • A spike beyond the plan. Repeat with a sharper join wave, as in a spike test, to see what happens when more people arrive than you forecast.

A load test does not measure rebuffering or picture quality on a device. Pair it with player analytics from real viewers to close that gap.

Running it with LoadFocus

LoadFocus runs k6 and JMeter scripts you upload from 25 cloud regions, with nothing to install, and its AI analysis summarises response times, errors and percentiles (loadfocus.com/load-testing and /k6-load-testing, read 2026-10-23). The load-testing page lists paid plans from 250 to 20,000 concurrent virtual users per test and 10 on the free plan. That is far below the audience of a very large event, so for those the sensible approach is to test the segment path and the backend at the highest load you can generate, then extrapolate with the arithmetic above and a CDN-side load test agreed with your provider. See the k6 load testing page and the load testing overview.

Frequently Asked Questions

How many virtual users do I need to simulate for a streaming launch?

Work from your forecast of peak concurrent viewers and the session length you test. Concurrent users equal arrival rate times session length. If you cannot generate the full audience, test the backend and origin at the highest load you can, and scale the result with the request arithmetic.

Can a load test measure buffering?

Not directly. It measures how quickly playlists and segments are served and how many fail. If segment times approach the segment duration, buffering is likely. Actual rebuffering is measured by player analytics from real viewers.

Should I load test the CDN?

Test the CDN path to see edge performance from your regions, and test the origin separately with cold caches. Read your CDN provider’s rules on load testing before you start.

How long should a streaming load test run?

Long enough to pass the join wave and hold the peak for several segment durations, so playlist reloads and cache behaviour settle. For a live event, match the hold to the expected peak window, and add a longer run if you suspect memory leaks, as in endurance testing.

Sources

  • RFC 8216, HTTP Live Streaming, section 6.3.4 (rfc-editor.org, read 2026-10-23)
  • Grafana k6 documentation, ramping-arrival-rate executor (grafana.com/docs/k6, read 2026-10-23)
  • loadfocus.com/load-testing and /k6-load-testing (read 2026-10-23)

Chris

Head of Content at LoadFocus

Chris leads content and oversees development across the services this blog covers. The guides and tool comparisons here come out of the same decisions that shape what ships.

Weekly tips right in your inbox.

Don’t miss out on the latest testing tips and tricks, tools and news related to software testing.

Already +20,000 members in the list.

The Load Testing Platform with AI That Explains Your Results

Load test websites and APIs from 25 cloud regions, monitor page speed and uptime, and get AI analysis that explains your results in plain English.

Cloud load testing, website speed and API monitoring in one place.

Hi there! Can I share a cool thing I'm working on with you?

A software testing newsletter that sparks joy.

Our goal is to create helpful content for software developers and testers.

If you're not into it, you can unsubscribe instantly.