Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 22 – Case studies: links, files and media

Design live cricket streaming like JioHotstar

Design live cricket streaming for tens of millions at once: encoding into short segments, shielded origins, many CDNs, edge-checked tokens and ad breaks.

  • Advanced
  • 40 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 7 of 40 minutes free
Free: 80 million screens at once, fed by shared segments. With a pass: the other 15 sections and 3 interview answers, about 33 minutes.

What you will learn

  • Estimate concurrency, egress and request rates for a match
  • Design live ingest, transcoding and packaging for a match
  • Choose a segment length from the delay and the requests it costs
  • Scale delivery through shields and several CDNs for sudden concurrency peaks
  • Prevent entitlement checks and ad breaks from becoming bottlenecks

Before you start

What you’ll learn · Before you start

What you will learn

  • Estimate concurrency, egress and request rates for a match
  • Design live ingest, transcoding and packaging for a match
  • Choose a segment length from the delay and the requests it costs
  • Scale delivery through shields and several CDNs for sudden concurrency peaks
  • Prevent entitlement checks and ad breaks from becoming bottlenecks

Before you start

On this page

Not affiliated

Based on public information about JioHotstar. MySmartCoPilot is not affiliated with JioHotstar, and JioHotstar’s real architecture may differ from what this lesson describes.

Live cricket streaming sends one match to tens of millions of screens at once, each a few seconds behind the ball. The pipeline runs in one direction: feeds from the ground are encoded into a ladder of bit rates, cut into segments of a few seconds and listed in playlists, and a shielded origin hands each new segment to the edges of several CDNs, which serve every player.

Cricket adds two hard parts to ordinary video. The audience arrives in waves that follow the game, a toss, a wicket, a tight last over, so capacity must be in place before the peak rather than added during it. And anything that would touch a central service once per viewer per segment, such as checking a subscription or choosing an ad, must happen once per viewing or once per group of viewers instead.

80 million screens at once, fed by shared segments

Ask these first, and note the answer you assume:

  • How many at once? JioStar reported 65.2 million peak concurrent viewers for a T20 World Cup semi-final between India and England (JioStar) and 72.5 million concurrent streams for the final between India and New Zealand (JioStar). Plan for 80 million.
  • On what? Mostly phones on mobile data, then connected TVs and browsers.
  • How far behind live? Under 20 seconds by default.
  • In which languages? JioStar describes its IPL coverage as more than 25 simultaneous feeds in 12 languages, so commentary comes in many languages over the same pictures.
  • Who may watch? Subscribers, by plan and region, on a limited number of devices.

The functional requirements: watch a match live on a phone, a TV or a browser, choose the commentary language, follow the score, and see ads in the breaks. The non-functional ones follow from the answers above: no stall at the moment everyone is watching, a start within a couple of seconds, a match that keeps playing when an encoder, a region or a whole CDN fails, and central services that never see one request per viewer per segment.

The estimate sheet of a match at its peak Python · estimate/match_sheet.py
# The estimate sheet of live cricket streaming at its peak (lesson system-design-hld/design-live-cricket-streaming).
# Every number below is an assumption of this lesson; the target sits a little above the largest concurrency a
# streaming service in India has reported, 72.5 million streams. Bit rates are megabits a second (10**6 bits).
PEAK_STREAMS = 80_000_000
SEGMENT_S = 4  # each media segment holds 4 seconds of video
REQUESTS_PER_SEGMENT = 2  # one segment and one playlist reload per segment for each viewer
EDGE_CACHES = 2_000  # cache servers, across CDNs and caches inside networks, that each fetch on their own
RENDITIONS = 6  # rungs of the bit-rate ladder
SHIELDS = 20  # the mid tier that edge caches fetch through
TOKEN_MINUTES = 10  # how long a playback token lasts before the player renews it

# The ladder and the share of viewers on each rung at the peak (a phone-heavy audience).
LADDER = {"180p": (0.25, 0.20), "360p": (0.6, 0.35), "480p": (1.0, 0.25), "720p": (2.0, 0.12),
          "1080p": (4.0, 0.06), "2160p": (12.0, 0.02)}
assert abs(sum(share for _, share in LADDER.values()) - 1) < 1e-9

avg = sum(mbit * share for mbit, share in LADDER.values())
edge = PEAK_STREAMS * REQUESTS_PER_SEGMENT / SEGMENT_S
no_shield = EDGE_CACHES * RENDITIONS * REQUESTS_PER_SEGMENT / SEGMENT_S
shielded = SHIELDS * RENDITIONS * REQUESTS_PER_SEGMENT / SEGMENT_S

print("Live cricket streaming: the estimate sheet at the peak")
print(f"  Streams      {PEAK_STREAMS / 10**6:,.0f} million at once")
print(f"  Bit rate     {avg:.2f} Mbit/s on average over the ladder's mix")
print(f"  Egress       {PEAK_STREAMS * avg / 10**6:,.1f} Tbit/s from the edges")
print(f"  Edge         {edge / 10**6:,.0f} million requests/s: a segment and a playlist every {SEGMENT_S} s per viewer")
print(f"  Origin       {no_shield:,.0f} requests/s if all {EDGE_CACHES:,} edge caches fetch directly, {shielded:,.0f} through {SHIELDS} shields")
print(f"  Tokens       {PEAK_STREAMS / (TOKEN_MINUTES * 60):,.0f} renewals/s for {TOKEN_MINUTES}-minute playback tokens,")
print(f"               against {PEAK_STREAMS / SEGMENT_S / 10**6:,.0f} million/s if every segment asked the entitlement service")

Output

Live cricket streaming: the estimate sheet at the peak
  Streams      80 million at once
  Bit rate     1.23 Mbit/s on average over the ladder's mix
  Egress       98.4 Tbit/s from the edges
  Edge         40 million requests/s: a segment and a playlist every 4 s per viewer
  Origin       6,000 requests/s if all 2,000 edge caches fetch directly, 60 through 20 shields
  Tokens       133,333 renewals/s for 10-minute playback tokens,
               against 20 million/s if every segment asked the entitlement service

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 match_sheet.py

At the peak the edges send 98.4 Tbit/s and take 40 million requests a second, far more than one provider should carry for one event, so delivery is spread over several CDNs and caches inside internet providers’ networks. The origin needs only 60 requests a second once the edges fetch through 20 shield tier: An extra cache layer between a CDN's edges and the origin. Every edge sends its misses there, so a file wanted at many edges costs the origin about one request instead of one per edge. More in “CDNs and edge caching”. And checking the subscription on every segment would cost 20 million calls a second, against 133,333 renewals of ten-minute playback tokens.

Exercise · Easy · Python

Size a live match and trace a cached segment

Write two functions in match_sheet.py.

match_sheet(streams, avg_mbit, segment_s, edge_caches, renditions, shields) returns four figures of a live stream's estimate sheet at its peak, as a dictionary. The parameters are the assumptions, with the lesson's values in brackets: streams watched at once (80,000,000), the average bit rate in megabits a second (1.23), the seconds of video in each segment (4), the edge caches that fetch on their own (2,000), the renditions of the ladder (6) and the shield caches that edges fetch through (20). Each viewer makes two requests per segment duration, one segment and one playlist reload, and so does each cache for each rendition. Return these keys:

  • "egress_tbit": the video leaving the edges, in terabits a second (a terabit is 10**6 megabits);
  • "edge_requests": requests a second that the edges receive from players;
  • "origin_direct": requests a second at the origin when every edge cache fetches from it;
  • "origin_shielded": requests a second at the origin when edges fetch through the shields.

cached_segment_path() returns, as a set, the components that do any work for one segment request when the edge already holds that segment, the player included. Choose them from the names in COMPONENTS, spelled as they are there.

The sample tests accept each figure within 10 %, as an estimate should; the set must be exact.

Starter code · match_sheet.py

COMPONENTS = {
    "player",
    "CDN edge",
    "shield",
    "origin packager",
    "live encoder",
    "entitlement service",
    "subscription database",
    "ad decision service",
}


def match_sheet(streams, avg_mbit, segment_s, edge_caches, renditions, shields):
    """Four figures of a live stream's estimate sheet at its peak, as a dictionary."""
    # Replace this line with your code.
    return {}


def cached_segment_path():
    """The components that work on one segment request when the edge already holds the segment."""
    # Replace this line with your code.
    return set()
The sample tests · test_match_sheet.py
import math

from match_sheet import COMPONENTS, cached_segment_path, match_sheet

LESSON = dict(streams=80_000_000, avg_mbit=1.23, segment_s=4, edge_caches=2_000, renditions=6, shields=20)
SMALL = dict(streams=5_000_000, avg_mbit=2.0, segment_s=6, edge_caches=300, renditions=5, shields=4)


def near(actual, expected):
    """Within 10%, as an estimate should be."""
    return math.isclose(actual, expected, rel_tol=0.10)


def test_egress():
    """turns streams and their average bit rate into terabits a second"""
    assert near(match_sheet(**LESSON)["egress_tbit"], 98.4)
    assert near(match_sheet(**SMALL)["egress_tbit"], 10.0)


def test_edge():
    """counts a segment and a playlist reload per viewer per segment duration"""
    assert near(match_sheet(**LESSON)["edge_requests"], 40_000_000)
    assert near(match_sheet(**SMALL)["edge_requests"], 1_666_667)


def test_origin():
    """counts the caches that fetch from the origin, each for every rendition"""
    lesson = match_sheet(**LESSON)
    assert near(lesson["origin_direct"], 6_000)
    assert near(lesson["origin_shielded"], 60)
    small = match_sheet(**SMALL)
    assert near(small["origin_direct"], 500)
    assert near(small["origin_shielded"], 6.67)


def test_cached_segment_path():
    """keeps every service behind the edge out of a cache hit"""
    path = cached_segment_path()
    assert path <= COMPONENTS, f"unknown names: {sorted(path - COMPONENTS)}"
    assert path == {"player", "CDN edge"}
A hint

Egress is streams * avg_mbit, divided by 10**6 to turn megabits into terabits. Requests a second are the number of requesters times 2, divided by segment_s: the requesters are the viewers at the edge, and the caches times the renditions at the origin. For the path, remember what the edge checks on its own: a signed token needs no call to anyone else.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Checkpoint

Check the estimate

  1. Question 1 of 2 80 million viewers watch with 4-second segments, and each player fetches one segment and reloads its playlist once per segment. How many million requests a second reach the edges?

    Type a number.

    A hint

    Two requests every 4 seconds for each viewer.

    Show the answer: Question 1 of 2

    Answer: 40 million a second (anything from 39 to 41 counts)

    2 requests ÷ 4 s × 80 million = 40 million a second, far more than one provider should carry for one event, so delivery is spread over several CDNs and caches inside internet providers' networks.

  2. Question 2 of 2 Why does the origin need only about 60 requests a second, while the edges take 40 million?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The edges fetch through 20 shields, and each shield fetches each new segment of each rendition once

    2,000 edge caches fetching on their own would send 6,000 requests a second; through 20 shields it is 60, one fetch per segment and rendition per shield.

The first design: one live path, and one call per viewing

Live cricket design: feeds are encoded into a ladder, packaged at a shielded origin and served by CDN edges that check signed tokens.Production at the groundvideo, commentary in each languageIngest in two regionsredundant contribution feedsLive encodersthe bit-rate ladderPackager and originsegments, playlists, ad markersShield tierone fetch per segment and renditionEdges of several CDNs andcaches inside networkscheck tokens, serve segmentsPlayersphones, TVs, browsersPlayback servicesubscription, signed token,which CDNAd decisionsper cohort, before each break1. contribution feeds2. one input per feed3. renditions4. misses onlymisses only5. press play6. segments and playlistsad pods

The live path of a cricket match, from the ground to the players

Text description of the diagram

The diagram runs from top to bottom.

Production at the ground makes the video and the commentary in each language. Its (1) contribution feeds go to ingest in two regions, so that one failure does not stop the match. Ingest (2) passes one input per feed to the live encoders, which (3) make every rendition of the bit-rate ladder. The packager and origin cuts the renditions into short segments, writes the playlists and places the ad markers.

The origin sends (4) only misses onward, to a shield tier that fetches each segment of each rendition once, and the shield tier in turn serves the misses of the edges. The edges belong to several CDNs and to caches inside the networks of internet providers; they check the signed token of every request and serve the segments.

A player first (5) presses play at the playback service, which checks the subscription, signs a token and says which CDN to use. From then on the player (6) gets segments and playlists from the edges only. A dashed line shows the ad decision service supplying ad pods per cohort of viewers to the origin before each break.

Follow the ball. The The video and sound sent from the ground to the encoders, usually over two separate paths, so that one failed link does not stop the match. reach ingest in two regions, encoders make every rung of the bitrate ladder: The set of renditions a video is encoded into, each a resolution and a bit rate, from which a player picks the rung its network can sustain. More in “Media pipelines: transcoding and adaptive bitrate”, and the packager cuts segments and updates playlists; only misses travel from the origin through the shields to the edges. A player presses play once at the playback service, which checks the subscription, signs a token and picks a CDN, and from then on it talks only to the edges. Step through it:

Interactive · step by step One segment of the match, from the ground to the phone Step through the live path of one segment, and the single call a viewer makes before watching.
One segment of the match, from the ground to the phone, step 7 of 7. Showing Production at the ground, Ingest in two regions, Live encoders, Packager and origin, Shield tier, Edges of several CDNs, Player, Playback service. In focus: Edges of several CDNs.Production at the groundIngest in two regionsLive encodersthe bit-rate ladderPackager and originsegments and playlistsShield tierone fetch per segmentEdges of several CDNscheck tokensPlayerphone, TV or browserPlayback servicesubscription, token, CDNmisses only

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. The feeds. Production at the ground sends the pictures and the commentary in each language to ingest in two regions, so that one failed link does not stop the match.
  2. The ladder. The live encoders turn each feed into every rung of the bit-rate ladder, from the low rungs phones need on weak networks to the top rung for televisions.
  3. Segments and playlists. The packager cuts each rung into 4-second segments and adds each new segment to that rung's playlist. The origin now holds the newest segment.
  4. Press play, once. The viewer presses play. The playback service checks the subscription, signs a token for this match and picks a CDN. It is the only call this viewing makes to a central service.
  5. Edges serve the player. From now on the player asks an edge for playlists and segments, and the edge checks the token on every request with keys it already holds.
  6. A new segment, fetched once. When the newest segment is not at an edge yet, the edge asks the shield tier, which fetches it from the origin once for every edge behind it.
  7. Misses only. The shield hands the segment to the edges that asked, and each edge serves it to every viewer nearby. At the peak 40 million requests a second reach the edges, and about 60 reach the origin.

The questions this design has to answer:

  • Where do the seconds of delay go, and what does a shorter segment cost?
  • How many requests reach the origin, and what can make that number explode?
  • How are a dozen commentary languages delivered without multiplying the cache?
  • How does an edge check every request without calling anyone?
  • What must be ready before the toss, and what is switched off when the peak outgrows the plan?
  • How are ads chosen for 80 million viewers who reach a break in the same seconds?
  • What happens when an encoder, a region or a CDN fails during the match?

Checkpoint

Check the first design

  1. Question 1 of 2 In the first design, how often does a player call the playback service?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Once when the viewer presses play, then it talks only to the edges

    One call per viewing, plus a renewal of the token every ten minutes, keeps the central service off the path of every segment.

  2. Question 2 of 2 A new segment is not at an edge yet. Where does the edge get it?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: From the shield tier, which fetches it from the origin once for every edge behind it

    The live path runs one way: ground, ingest, encoders, packager and origin, shields, edges, players. Each layer passes on only what it misses.

Each segment of delay costs requests: 15 seconds and 40 million a second at 4 s Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • The origin sees 60 requests a second, until a token enters the cache key
  • A dozen languages share one set of video segments
  • Edges check every request with a token, and renew it 18 times a match
  • Capacity is in place before the toss, and the peak degrades in a fixed order
  • Ads are decided per cohort during the over, not per player at the break
  • Alerts wait for the picture, so no score runs ahead of it
  • Failure drills
  • Bottlenecks beyond the plan, with numbers
  • Alternatives considered and rejected
  • The seven questions, answered
  • The bar at each level, and a 45-minute rehearsal
  • Practise: the whole match, one question at a time
  • Interview questions
    • Why is a live match delivered as short segments over HTTP rather than as one continuous stream per viewer?
    • Viewers double from 40 to 80 million during the last overs of a close chase. What breaks first in your design, and what did you prepare before the match so that nothing does?
    • Ten minutes into a match, requests at the origin jump from about 60 a second to millions, while the number of viewers stays flat. What do you check first, and how do you stop it?
    • Every viewer reaches an ad break within the same 15 seconds. Design ad insertion so that 80 million viewers see ads without overloading the ad decision service or delaying the match.
  • Key takeaways

4 diagrams · 4 runnable examples (JavaScript, Python) · 3 interview answers · about 48 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design a URL shortener with click analytics

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.