Buffer the whole export and the caller waits

six seconds for the first byte.

buffered — Results.Ok(await ReadAllRowsAsync(ct)) first byte 6,300 ms
streamed — return ReadRowsAsync(ct) first byte 29 ms
0 msboth finish near 6,400 ms — the six-second drain, not the response, sets the floor6,430 ms
bufferedstreamed time to first byte6,300 ms29 ms peak managed heap39.4 MB17.0 MB response body21.1 MB21.1 MB
the price: a failure after the first flush
status200 OK
content-length(none — chunked)
reading the bodythrows
The status line left with the first chunk, so there is no 500 to send. A client that retries on non-2xx will not retry this.
measured: .NET 10 · 200,000 rows · source pages every 500 rows, 15 ms per page
gdhami.net