v0.28.1
[0.28.1] — 2026-06-02
PATCH release — fixes a Compression + StaticFiles interaction
discovered while preparing the Sprint 29 HttpArena leaderboard
submission. Adds precompressed-variant serving so a static-file
workload with Accept-Encoding: br/gzip/zstd no longer engages
on-the-fly compression for every request. Adds backpressure on
the Compression executor so the same workload degrades gracefully
when no precompressed sibling is available instead of collapsing
under burst load.
Fixed
Compressionmiddleware emitted duplicatehttp.response.start
events when the upstream response was already encoded. Under
HTTP/1.1 keep-alive this caused the sender to treat the second
start as the end of the first response and close the connection
— visible as a 1:1 success/read-error ratio inwrkand a
~500× throughput drop onAccept-Encoding-bearing static
workloads. Now: whenskip_compressiontriggers, the start
event is forwarded inline and the outer code path returns
early. Regression test added at
tests/unit/test_compression_backpressure.py::test_skip_path_emits_exactly_one_start_event.
Added
- Precompressed-variant serving in
StaticFiles. When the
client offersAccept-Encoding: br | gzip | zstdand a
<path>.br/.gz/.zstsibling exists on disk,
StaticFilesserves that file directly with the matching
Content-Encodingheader (andVary: Accept-Encoding). No
on-the-fly compression on the static hot path. Server
preference order matches theCompressionmiddleware
(br > zstd > gzip). Range requests bypass sibling lookup
to avoid encoded-vs-Range size confusion. Same pattern as
nginxgzip_static, Caddyfile_server { precompressed },
Apachemod_negotiation. Compressionexecutor-queue backpressure. New
constructor argumentexecutor_max_inflightand env var
BB_COMPRESSION_MAX_INFLIGHT(default
max(os.cpu_count() * 2, 4)). When at the cap, additional
eligible responses are served uncompressed rather than
queued. Prevents the unbounded executor backlog that caused
the HttpArenastaticprofile to collapse to 0 r/s on
run 2/3 under c=1024.0disables the cap (pre-0.28.1
unbounded behaviour, if you want it back).Compressionskips already-encoded responses. When the
upstream response has aContent-Encodingheader set (e.g.
by the new precompressed-variantStaticFilespath), the
middleware forwards as-is rather than wrapping again. Same
shape Starlette / Caddy / nginx use.
Changed
StaticFilescache key extended to record content-encoding
alongside (path, mtime, size). Different encodings of the
same file now coexist in the cache as separate entries.
Local benchmark — three back-to-back wrk passes, c=1024
| Workload | 0.28.0 | 0.28.1 |
|---|---|---|
Accept-Encoding: br + precompressed sibling |
54 / 0 / 0 r/s | 54,664 / 34,380 / 34,920 r/s |
Accept-Encoding: br + no sibling (backpressure) |
54 / 0 / 0 r/s | 3,857 / 3,994 / 3,951 r/s stable |
No Accept-Encoding (no Compression engagement) |
24,572 / 27,386 / 31,358 r/s | unchanged |
Tests
- +10 unit tests.
tests/unit/test_static.pygains 9 tests
covering precompressed-variant negotiation (br/gzip/zstd
preference, q=0 refusal, Range bypass, no-sibling fall-through,
cache hits, separate-encoding cache entries).
tests/unit/test_compression_backpressure.pyis new with 6
tests covering the executor-inflight counter (under cap →
compresses; at cap → serves uncompressed; counter decrement on
success and on exception; small-body path bypasses the cap;
skip-path emits exactly one start event). Total unit-test
count: 812 passing.
Notes for adopters
- For
staticcontent under burst load, the right pattern is to
ship precompressed.br/.gz/.zstsiblings on disk
(build-time step) and rely on the new variant-serving path.
Compression on the fly via theCompressionmiddleware is
fine for small dynamic responses but doesn't scale to thousands
of concurrent requests on large bodies — for that, terminate
compression at a CDN or reverse proxy.