fastapi 0.161.1, starlette 1.9.0, uvicorn 0.54.0, httpx 0.28.1, python 3.12.15 simulated: retrieval 50 ms, LLM first token 400 ms, 60 tokens x 20 ms | Case | median first byte ms | median sources ms | median first token ms | median total ms | worst first byte ms | |---|---|---|---|---|---| | non-streaming JSON, 1 client | 1664 | - | - | 1664 | 1666 | | SSE sources-first, 1 client | 52 | 52 | 453 | 1673 | 53 | | SSE sources-first, 20 concurrent | 71 | 71 | 472 | 1715 | 86 | | SSE + blocking time.sleep, 5 concurrent | 3280 | 3280 | 3681 | 4894 | 6510 | | SSE sources-first, 5 concurrent (control) | 54 | 54 | 455 | 1685 | 56 | | SSE + GZipMiddleware, 1 client | 52 | 52 | 453 | 1673 | 53 | | SSE + GZipMiddleware, client sends Accept-Encoding: gzip | 52 | 52 | 453 | 1673 | 53 | chunks received per response (1 client, no gzip): 62 of 62 events chunks with gzip + Accept-Encoding: 62