Skip to content

fastapi: emit a single Server header and stop gzip-inflating tiny bodies - #1054

Merged
Kaliumhexacyanoferrat merged 2 commits into
MDA2AV:mainfrom
TOKUJI:fix/fastapi-server-header-gzip-minsize
Jul 26, 2026
Merged

fastapi: emit a single Server header and stop gzip-inflating tiny bodies#1054
Kaliumhexacyanoferrat merged 2 commits into
MDA2AV:mainfrom
TOKUJI:fix/fastapi-server-header-gzip-minsize

Conversation

@TOKUJI

@TOKUJI TOKUJI commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #1052.

  • Server header: drop the BaseHTTPMiddleware-based ServerHeaderMiddleware and pass --no-server-header --header Server:FastAPI to uvicorn instead. Responses previously carried both server: uvicorn and server: FastAPI; they now carry exactly one server: FastAPI, at zero per-request cost.
  • GZip: minimum_size=11000 — the value in FastAPI's own GZipMiddleware docs example; compresslevel=5 unchanged. Happy to switch to Starlette's default (500) if you prefer.

Verified by building the entry's Dockerfile (uvicorn 0.40.0) and probing the container:

  • /baseline11?a=13&b=42200, single server: FastAPI, and no Content-Encoding even with Accept-Encoding: gzip (the 2-byte body is no longer inflated)
  • /json/50?m=1 with Accept-Encoding: gzip, brContent-Encoding: gzip (7602 B → 423 B); no Content-Encoding without Accept-Encoding — the json-comp validation checks still pass

🤖 Generated with Claude Code

- Replace the BaseHTTPMiddleware-based ServerHeaderMiddleware with
  uvicorn's --no-server-header --header Server:FastAPI: responses
  previously carried both 'server: uvicorn' and 'server: FastAPI',
  now exactly one 'server: FastAPI' at zero per-request cost
- Raise GZipMiddleware minimum_size from 1 to 1000 (the value in
  FastAPI's own docs example; compresslevel=5 unchanged) so tiny
  bodies are no longer inflated by compression

Fixes MDA2AV#1052

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Repository owner deleted a comment from github-actions Bot Jul 26, 2026
@Kaliumhexacyanoferrat

Copy link
Copy Markdown
Collaborator

/benchmark -f fastapi --save

@github-actions

Copy link
Copy Markdown
Contributor

👋 /benchmark request received. A collaborator will review and approve the run.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: fastapi | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
baseline 512 320,447 6505.3% 4.5GiB +129.2% -4.3%
baseline 4096 314,605 6506.2% 4.6GiB +154.7% -13.2%
pipelined 512 364,432 6524.6% 4.5GiB +150.0% -6.2%
pipelined 4096 359,847 6524.2% 4.7GiB +193.5% -14.5%
limited-conn 512 284,181 6508.9% 5.7GiB +119.5% +11.8%
limited-conn 4096 286,820 6496.5% 5.8GiB +146.6% +5.5%
json 4096 157,204 6468.8% 4.8GiB +83.6% -9.4%
json-comp 512 93,695 6450.8% 4.7GiB +45.2% -2.1%
json-comp 4096 93,953 6445.4% 4.7GiB +50.6% -13.0%
json-comp 16384 92,206 6450.5% 4.9GiB +65.4% -26.9%
json-tls 4096 135,982 6176.2% 4.8GiB +78.9% -15.8%
upload 32 2,125 2532.7% 4.6GiB +37.9% ~0%
upload 256 1,536 6271.6% 4.8GiB +6.7% -4.0%
api-4 256 8,449 401.4% 494MiB +10.7% -0.2%
api-16 1024 30,215 1616.1% 1.7GiB +61.8% +13.3%
static 1024 22,055 6702.8% 5.3GiB +12.9% -7.0%
static 4096 20,911 6765.1% 6.8GiB +16.9% -4.2%
static 6800 20,315 6712.9% 7.9GiB +17.0% -3.7%
async-db 1024 76,351 6248.4% 4.8GiB +39.9% -4.0%
Full log
[run 1/3]
Running 5s test @ http://localhost:8080
  64 threads and 4096 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   191.84ms   96.00ms 978.58ms   80.71%
    Req/Sec   326.92    109.72   760.00     81.88%
  98065 requests in 5.12s, 1.72GB read
Requests/sec:  19137.45
Transfer/sec:    343.34MB
[info] CPU 6618.8% | Mem 6.6GiB

[run 2/3]
Running 5s test @ http://localhost:8080
  64 threads and 4096 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   187.91ms   64.01ms 472.21ms   81.41%
    Req/Sec   335.26     47.70   580.00     78.79%
  106844 requests in 5.11s, 1.87GB read
Requests/sec:  20911.57
Transfer/sec:    375.36MB
[info] CPU 6765.1% | Mem 6.8GiB

[run 3/3]
Running 5s test @ http://localhost:8080
  64 threads and 4096 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   189.01ms   65.52ms 495.68ms   80.92%
    Req/Sec   333.20     46.57   575.00     75.96%
  106186 requests in 5.11s, 1.86GB read
Requests/sec:  20781.65
Transfer/sec:    372.96MB
[info] CPU 6567.0% | Mem 6.9GiB

=== Best: 20911 req/s (CPU: 6765.1%, Mem: 6.8GiB) ===
[info] saved results/static/4096/fastapi.json
httparena-bench-fastapi
httparena-bench-fastapi

==============================================
=== fastapi / static / 6800c (tool=wrk) ===
==============================================
[info] waiting for server...
[info] server ready

[run 1/3]
Running 5s test @ http://localhost:8080
  64 threads and 6800 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   302.15ms  158.69ms   1.60s    74.67%
    Req/Sec   326.63    141.93     1.03k    81.40%
  96518 requests in 5.12s, 1.68GB read
Requests/sec:  18843.05
Transfer/sec:    336.70MB
[info] CPU 6577.7% | Mem 7.6GiB

[run 2/3]
Running 5s test @ http://localhost:8080
  64 threads and 6800 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   311.88ms  109.25ms 771.69ms   81.51%
    Req/Sec   330.36     76.31     0.91k    82.97%
  104961 requests in 5.17s, 1.83GB read
Requests/sec:  20315.55
Transfer/sec:    363.17MB
[info] CPU 6712.9% | Mem 7.9GiB

[run 3/3]
Running 5s test @ http://localhost:8080
  64 threads and 6800 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   312.95ms  110.57ms 785.71ms   81.23%
    Req/Sec   329.08     76.66     0.95k    82.69%
  102865 requests in 5.10s, 1.80GB read
Requests/sec:  20153.35
Transfer/sec:    360.40MB
[info] CPU 6450.0% | Mem 8.0GiB

=== Best: 20315 req/s (CPU: 6712.9%, Mem: 7.9GiB) ===
[info] saved results/static/6800/fastapi.json
httparena-bench-fastapi
httparena-bench-fastapi

==============================================
=== fastapi / async-db / 1024c (tool=gcannon) ===
==============================================
[info] resetting postgres for a clean per-profile baseline
[info] starting postgres sidecar
httparena-postgres
[info] postgres ready (seeded)
[info] waiting for server...
[info] server ready

[run 1/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   12.08ms   2.36ms   4.92ms   267.60ms    1.38s

  763544 requests in 10.00s, 763515 responses
  Throughput: 76.33K req/s
  Bandwidth:  287.35MB/s
  Status codes: 2xx=763515, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 763514 / 763515 responses (100.0%)
  Latency overflow (>5s): 1
  Reconnects: 30281
  Per-template: 152199,152902,153113,153190,152110
  Per-template-ok: 152199,152902,153113,153190,152110
[info] CPU 6248.4% | Mem 4.8GiB

[run 2/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   12.12ms   2.40ms   4.89ms   260.80ms    1.39s

  760175 requests in 10.00s, 760143 responses
  Throughput: 76.00K req/s
  Bandwidth:  286.11MB/s
  Status codes: 2xx=760143, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 760143 / 760143 responses (100.0%)
  Latency overflow (>5s): 4
  Reconnects: 30241
  Per-template: 151918,152278,152135,151917,151895
  Per-template-ok: 151918,152278,152135,151917,151895
[info] CPU 6325.2% | Mem 4.8GiB

[run 3/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   12.32ms   2.33ms   4.76ms   268.70ms    1.44s

  756903 requests in 10.00s, 756870 responses
  Throughput: 75.67K req/s
  Bandwidth:  285.10MB/s
  Status codes: 2xx=756870, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 756869 / 756870 responses (100.0%)
  Latency overflow (>5s): 4
  Reconnects: 30079
  Per-template: 151191,151272,151480,151804,151122
  Per-template-ok: 151191,151272,151480,151804,151122
[info] CPU 6298.6% | Mem 4.8GiB

=== Best: 76351 req/s (CPU: 6248.4%, Mem: 4.8GiB) ===
[info] input BW: 5.10MB/s (avg template: 70 bytes)
[info] saved results/async-db/1024/fastapi.json
httparena-bench-fastapi
httparena-bench-fastapi
[info] skip: fastapi does not subscribe to crud
[info] skip: fastapi does not subscribe to fortunes
[info] skip: fastapi does not subscribe to baseline-h2
[info] skip: fastapi does not subscribe to static-h2
[info] skip: fastapi does not subscribe to baseline-h2c
[info] skip: fastapi does not subscribe to json-h2c
[info] skip: fastapi does not subscribe to baseline-h3
[info] skip: fastapi does not subscribe to static-h3
[info] skip: fastapi does not subscribe to gateway-64
[info] skip: fastapi does not subscribe to gateway-h3
[info] skip: fastapi does not subscribe to production-stack
[info] skip: fastapi does not subscribe to unary-grpc
[info] skip: fastapi does not subscribe to unary-grpc-tls
[info] skip: fastapi does not subscribe to stream-grpc
[info] skip: fastapi does not subscribe to stream-grpc-tls
[info] skip: fastapi does not subscribe to echo-ws
[info] skip: fastapi does not subscribe to echo-ws-pipeline
[info] skip: fastapi does not subscribe to echo-ws-limited
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/results/fastapi.json - 19 new, 19 total
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
[info] restoring loopback MTU to 65536

@Kaliumhexacyanoferrat

Copy link
Copy Markdown
Collaborator

Okay, wow 😄

@Kaliumhexacyanoferrat
Kaliumhexacyanoferrat merged commit adeaf3a into MDA2AV:main Jul 26, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fastapi: responses carry two Server headers; GZipMiddleware(minimum_size=1) inflates tiny bodies

2 participants