§4.5
Chapter 04 · Stream Multiplexing and Flow Control for Performance

§4.5Example: Designing a Stream Plan for Mixed Latency Workloads

RFC 9000

Learning objective. Put streams, flow control, prioritization, and loss isolation together by designing a concrete stream plan for an application whose traffic mixes render-critical, bulk, and real-time data.

The workload #

Consider a single connection serving a rich web application. Its traffic falls into classes with genuinely different needs:

  • Render-critical. The HTML document, the style sheet, the main script. Must arrive reliably and early; a page cannot paint without them.
  • Bulk media. Images, fonts, a video segment. Reliable, but not render-blocking; users tolerate progressive arrival.
  • Real-time. Live telemetry, cursor/position updates, a presence heartbeat. Latency- sensitive and disposable: a late value is worthless (§3.4).
  • Background. Prefetch, analytics beacons, software updates. Should never contend with anything above.

The design task is to map each class onto the right transport primitive using the four levers from this chapter: reliable stream vs datagram, one stream per object vs shared, urgency, and incremental.

A stream plan #

Class Primitive Per object? urgency (u) incremental (i)
HTML document reliable bidi stream yes 1 no
CSS / JS (render-blocking) reliable bidi stream yes 2 no
Images / fonts reliable bidi stream yes 4 yes
Live telemetry / positions DATAGRAM n/a n/a n/a
Prefetch / analytics / updates reliable bidi stream yes 7 no
ClientServerone connection carrying a mixedworkloada loss on stream 12 blocks onlyhero.jpg — css, js, telemetry unaffectedstream 0: index.html (u=1, reliable)stream 4: app.css (u=2,non-incremental)stream 8: app.js (u=2,non-incremental)streams 12, 16: hero.jpg / photo.jpg(u=4, incremental, round-robin)DATAGRAM: live telemetry(unreliable, not retransmitted)
Fig. 4.5-1The plan in motion. Render-critical resources go first on their own streams, images round-robin at lower priority, and real-time telemetry rides datagrams — so a loss on one image stream isolates to that image.RFC 9000 §2; RFC 9218 §4; RFC 9221

Every reliable object gets its own stream, so a loss isolates to that object (§4.4) and the server can schedule them independently by urgency (§4.3). Render-critical resources take the lowest urgency values so they win the shared pipe; images share a lower priority level as incremental so they render progressively in round-robin rather than one-at-a-time; background traffic sits at urgency 7 where it yields to everything. Telemetry leaves the stream world entirely for datagrams: unreliable and unordered, so it can never head-of-line-block a real request and never wastes bandwidth retransmitting a stale position.

Sizing and pitfalls #

Two cross-cutting choices finish the plan:

  • Flow-control windows for the bulk class. The media transfers are the ones that need a window covering the bandwidth-delay product (§4.2); size initial_max_data and the stream windows for them, and make sure a stalled media reader cannot exhaust the shared connection window and starve the render-critical streams.
  • Stream-count limits for the concurrency. A page opening dozens of object streams at once will stall on STREAMS_BLOCKED if initial_max_streams_bidi is set for a handful (§4.1); provision the limit for the fan-out you expect.
In practice

editorial The single highest-leverage decision here is splitting real-time off the reliable path. Teams often push position updates or telemetry down a normal stream "because it's simpler," then discover that under loss those updates queue behind their own retransmissions and arrive in a stale burst. Moving them to datagrams removes both the head-of-line coupling and the wasted retransmission in one change. The second-highest is not over-bundling reliable objects: keep them on separate streams so loss and priority act per object, not per bundle (§4.4).

Takeaways #

A good stream plan is four decisions per traffic class — reliable-or-datagram, per-object-or- shared, urgency, incremental — plus flow-control and stream-count sizing for the whole connection. Render-critical resources get their own high-priority streams, bulk media round-robins beneath them, real-time data rides datagrams, and background yields to all. That completes the streams-and-flow-control chapter; Chapter 5 moves up a layer to how HTTP/3 frames turn these streams into requests and responses.