There's an important optimization that Nginx is missing around real-world TTFB, however that would benefit Cloudflare users.
Even though it is streaming compression, zlib normally packs compressed content into larger than 1500-byte blocks. Browsers can start parsing gzipped content as soon as they can decompress a block, but they have to wait for a whole block to arrive, which means for gzipped content they will often have to wait for more than the first packet to arrive. (Due to TCP slow-start, this may be another round-trip.) This means they are also waiting longer to start fetching <head> contents.
There's a simple fix for this, which is to call deflate(..., Z_SYNC_FLUSH) on a chunk that is likely to compress to under 1500 bytes, like maybe all of <head> or the first 4k. The total compressed size will be slightly larger, but the tradeoff is usually worth it. Nginx doesn't currently do this, but would be a nice optimization to make available.
It's possible to work around this in Nginx by using the embedded perl module and SSI. After </head>, I use SSI to call perl's $r->flush, which Nginx correctly translates into Z_SYNC_FLUSH. The improvement is small, but measurable.
Even though it is streaming compression, zlib normally packs compressed content into larger than 1500-byte blocks. Browsers can start parsing gzipped content as soon as they can decompress a block, but they have to wait for a whole block to arrive, which means for gzipped content they will often have to wait for more than the first packet to arrive. (Due to TCP slow-start, this may be another round-trip.) This means they are also waiting longer to start fetching <head> contents.
There's a simple fix for this, which is to call deflate(..., Z_SYNC_FLUSH) on a chunk that is likely to compress to under 1500 bytes, like maybe all of <head> or the first 4k. The total compressed size will be slightly larger, but the tradeoff is usually worth it. Nginx doesn't currently do this, but would be a nice optimization to make available.
It's possible to work around this in Nginx by using the embedded perl module and SSI. After </head>, I use SSI to call perl's $r->flush, which Nginx correctly translates into Z_SYNC_FLUSH. The improvement is small, but measurable.