advanced25 min studyLesson 203 in Engineering

HTTP/2 multiplexes streams with two levels of DATA credit

Track per-stream and connection-level flow-control windows while separating stream concurrency, frame limits, and underlying TCP ordering.

On this page

What you’ll understand

  • Debit both flow-control budgets for an HTTP/2 DATA frame.
  • Distinguish DATA flow control from stream limits and control frames.
  • Explain why HTTP/2 multiplexing does not remove TCP byte-order blocking.

Putting many requests on one connection replaces a pool of sequential exchanges with a set of stream state machines. HTTP/2 labels frames with stream identifiers so the endpoints can interleave those machines. The receiver still needs protection from excess DATA, both within one stream and across the connection. Learn to keep those budgets separate before interpreting a stalled stream as a stalled network or assuming that every frame consumes identical credit.

Multiplexing is structured interleaving

An HTTP/2 connection carries frames, many of which belong to identified streams. Request and response messages use header blocks and optional DATA, with flags and frame types determining message and stream transitions. Stream identifiers correlate exchanges; arbitrary application messages are not inferred from TCP read boundaries. A peer's stream-concurrency limit governs new-stream admission using the relevant open and half-closed streams, while maximum frame size constrains an individual frame. If the peer lowers SETTINGS_MAX_CONCURRENT_STREAMS below the existing count, it can let those streams finish; the lower limit does not require immediate closure of the excess. Neither is a byte window. An application can have many open streams and still be unable to send more body DATA because receive credit is exhausted.

Streams share one ordered TCP connection in each direction. If an earlier TCP byte range is missing, later HTTP/2 frames cannot be delivered to the parser even if they concern otherwise independent streams. This transport-level head-of-line dependency coexists with useful application multiplexing. Once bytes are available, endpoint scheduling also determines which streams receive service. An allowed concurrency of one hundred streams is therefore neither a promise of one hundred independent paths nor proof that all requests progress fairly. Inspect stream state, application scheduling, TCP recovery, and connection resources as different layers.

Ncounted+1≤Npermittedfor new-stream admission,Lframe≤LnegotiatedN_{\rm counted}+1\leq N_{\rm permitted}\quad\text{for new-stream admission},\qquad L_{\rm frame}\leq L_{\rm negotiated}
For admission under an unchanged limit, N_counted includes relevant open and half-closed streams before opening one more. A limit reduction can leave an allowed existing excess while those streams finish. L_frame is frame payload bytes under frame-size rules; neither constraint is a DATA-credit window.↔ Scroll wide equations horizontally.

DATA spends stream and connection credit

HTTP/2 flow control applies to DATA frames at both stream and connection scope. Sending a positive DATA payload requires enough credit in both windows. Frame payload bytes used for flow control include the Pad Length field and padding when present, not just useful application data; the nine-byte frame header is excluded. This makes padded frames consume more credit than their useful body alone. Other frame types, including WINDOW_UPDATE, are not themselves flow controlled in this way, which allows credit and control information to move even when DATA sending is blocked.

WINDOW_UPDATE adds credit at the named scope: a stream update does not automatically replenish the connection window. The receiver must process frames and manage connection credit even if one application stream reads slowly; otherwise unrelated traffic can stall. Initial stream-window settings and connection-window updates have different effects, and a decrease to initial stream windows can produce a temporarily negative stream window. A simplified positive-credit calculation is useful for a snapshot, but it is not a substitute for the specification's signed state and error handling during settings changes. Do not fix an application deadlock by sending illegal oversized DATA.

D≤min⁡(Ws,Wc,Lmax⁡),Ws′=Ws−D,Wc′=Wc−DD\leq\min(W_s,W_c,L_{\max}),\qquad W_s'=W_s-D,\quad W_c'=W_c-D
For a simple positive-credit snapshot, D is DATA frame payload bytes including any padding fields, W_s and W_c are stream and connection credit bytes, and L_max the permitted frame payload size. The nine-byte frame header is not charged; settings changes and zero-length control cases need additional rules.↔ Scroll wide equations horizontally.

Observe which scope actually stops progress

When one stream stalls, first ask whether its sender has data, whether stream credit is exhausted, whether connection credit is exhausted, and whether the transport or application is making progress. A connection-credit stall can affect many streams even when each has positive individual credit. Conversely, a stalled stream need not block unrelated streams if connection state is processed and resources remain available. Cancellation with RST_STREAM changes stream state but does not erase DATA already in flight from connection-level accounting. Keep resource release and late-frame handling consistent with the protocol instead of assuming cancellation rewinds transmission.

The queue lab isolates receive-consumption pressure without implementing those budgets. For EACH run Reset, explicitly set BOTH λ and μ, predict, then Play or Step: compare (3,2) with (1,2). Starting from four normalized units at t=0, one grows and the other empties at four seconds. Editing a rate retains t and recomputes from four rather than continuing a changed-rate trace. This aggregate fluid queue has no streams, WINDOW_UPDATE, padding, or TCP loss. Use it to explain why capacity must be bounded, and use the worked ledger to identify the exact exhausted HTTP/2 scope.

Positive stream credit does not override a connection limit

A stream has 6,000 bytes of DATA credit and its connection has 9,000 bytes. It sends an unpadded 4,000-byte DATA payload. Then another stream consumes 4,000 connection-credit bytes. Ignore all other limits and updates.

  1. The first DATA frame consumes 4,000 bytes from both relevant windows, leaving this stream with 2,000 and the connection with 5,000 bytes.

  2. The other stream's DATA consumes another 4,000 connection bytes, leaving connection credit 1,000. It does not debit this first stream's 2,000-byte window.

  3. The first stream can now send at most min(2,000,1,000)=1,000 further DATA payload bytes, provided frame-size rules allow it. A stream-only update would not remove this connection bottleneck.

The result

The binding budget is connection credit even though the first stream still has 2,000 bytes of individual permission.

Explore the model

Interactive lab

Interactive lab · queue

Why aggregate DATA needs a receive budget

Reset, set BOTH λ=3 and μ=2, predict, then Play or Step. Reset and re-set BOTH λ=1 and μ=2 for a fresh comparison starting at backlog four and t=0; it drains by t=4 seconds. Rate edits retain t and recompute from four. No stream windows, connection windows, frames, or updates are simulated.

Why aggregate DATA needs a receive budgetFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 s

Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forReceive-consumption pressure motivates flow control, but only explicit per-scope accounting identifies the HTTP/2 budget that blocks DATA.

Check your understanding

A stream has 5,000 DATA-credit bytes, but the connection window is zero. What may the sender infer?

Try it yourself

A DATA frame carries 100 application bytes, a one-byte Pad Length field, and 20 padding bytes. Calculate its flow-control charge and total frame bytes including the nine-byte HTTP/2 header.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

The DATA payload, including padding-related bytes, is charged; the fixed frame header is extra wire structure.

Compare with the solution

The DATA payload is 100+1+20=121 bytes, so both the stream and connection windows are debited by 121. Including the nine-byte frame header gives 130 HTTP/2 frame bytes, before TCP, TLS, or lower-layer overhead.

Take it with you

  • Stream concurrency, frame-size limits, and DATA credit constrain different resources.
  • Positive DATA consumes both stream and connection windows, including padding payload.
  • Multiplexed HTTP/2 streams retain TCP ordering and shared-resource dependencies.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.