I work on OnePassApps, so this is our own site and our own API, and every number below was measured on them today with plain HTTPS requests from one server - no browser session, no cookies, no JavaScript.
The question is narrow: when you ask for a page from app.onepassapps.com, how many bytes actually cross the wire?
We answered it by asking for every public resource we serve four ways - with no Accept-Encoding, then gzip, then br, then the string Chrome sends today (gzip, deflate, br, zstd) - and reading Content-Encoding, Content-Length, Transfer-Encoding, ETag and Vary off each answer. One request, four answers per resource, sixteen resources.
The table
| Resource | Uncompressed | gzip | brotli | gzip saves | brotli saves |
|---|---|---|---|---|---|
/ (home) | 25,158 | 6,813 | 6,809 | 72.9% | 72.9% |
/guides (index) | 61,760 | 13,372 | 12,911 | 78.3% | 79.1% |
one guide page (/guides/newsflow) | 26,600 | 7,092 | 6,938 | 73.3% | 73.9% |
one app page (/apps/newsflow) | 19,132 | 5,617 | 5,531 | 70.6% | 71.1% |
one studio page (/studios/image) | 17,379 | 5,116 | 5,068 | 70.6% | 70.8% |
/sitemap.xml | 4,046 | 514 | 475 | 87.3% | 88.3% |
/robots.txt | 160 | 118 | 104 | 26.2% | 35.0% |
/llms.txt | 17,965 | 4,896 | 4,944 | 72.7% | 72.5% |
/site.webmanifest | 876 | 399 | 392 | 54.5% | 55.3% |
app bundle index-LNYK_bk0.js | 324,591 | 91,293 | 90,675 | 71.9% | 72.1% |
fallback stylesheet shell-fallback.css | 3,054 | 1,175 | 1,155 | 61.5% | 62.2% |
icon-512.png | 18,385 | 18,385 | 18,385 | 0.0% | 0.0% |
/api/plans | 4,020 | 1,193 | 1,192 | 70.3% | 70.3% |
/api/health | 410 | 290 | 273 | 29.3% | 33.4% |
/api/voting | 4,146 | 1,227 | 1,224 | 70.4% | 70.5% |
/api/products | 15,650 | 1,776 | 1,845 | 88.7% | 88.2% |
Every size above is the byte count we received for that one response, not a size we calculated.
The app host answers no zstd at all
Ask the app host for zstd on its own and it answers uncompressed. We asked seven resources that way - the home page, /guides, /llms.txt, /sitemap.xml, the app bundle, robots.txt and the PNG - and every single one came back with no Content-Encoding at all. The full 25,158-byte home page, every time.
The API host answers the same request with Accept-Encoding: zstd served back as Content-Encoding: zstd. So the two hosts behind one product negotiate compression differently, and only one of them knows zstd exists.
On the API host, the route decides the encoding
When a browser sends gzip, deflate, br, zstd, our API host does not answer the same way on every route:
-
/api/healthanswers zstd - 285, 285 and 287 bytes across three identical requests. -
/api/runtimeanswers zstd - about 304 to 306 bytes. -
/api/auth/configanswers zstd - 284, 285 and 286 bytes. - The 404 route answers zstd too - 120 bytes.
-
/api/plansanswers gzip - 1,192 bytes. -
/api/votinganswers gzip - 1,226 to 1,228 bytes. -
/api/productsanswers gzip - 1,776 to 1,779 bytes.
Three repeats each, the same answer every time. One browser, one request header, three different encodings across our own API.
The routes that vary by encoding are not the ones that declare it
Vary is the header that tells a cache which request headers change the answer. On the three API routes that answer gzip, Vary does include Accept-Encoding - Accept-Encoding, Origin, and on the voting route Authorization, Cookie, Accept-Encoding, Origin.
On the four routes that answer zstd, Vary reads Origin only. Yet their bytes do change with Accept-Encoding: /api/health is 410 bytes uncompressed, 285-290 with gzip, 271-274 with brotli and 285-287 with zstd.
The app host declares it on the HTML pages, on /llms.txt and on /site.webmanifest (vary: accept-encoding), and does not declare it on /robots.txt or on the hashed app bundle.
gzip beat brotli twice
Brotli is usually the smaller answer, but not here, and not on our two smallest text payloads.
On /llms.txt, gzip came in at 4,896 bytes on every run, while brotli came in at 4,944 bytes on one pass and 4,952 bytes on another - so brotli was 48 and then 56 bytes larger than gzip.
On /api/products, gzip was 1,776 to 1,779 bytes and brotli was 1,843 to 1,847 - gzip roughly 68 bytes smaller again.
Brotli wins clearly on the big HTML and on the 324 KB app bundle (90,675 against 91,293). It loses on llms.txt and on the products catalogue. Whichever encoder answers is not always the one that ships fewer bytes.
The encoding a route picks is not always the smallest one available
Even where zstd is on the table it does not always win on size. /api/health in brotli is 271-274 bytes against 285-287 in zstd, and /api/plans in brotli is 1,192 bytes against 1,245 in zstd.
The ETag weakens when the body is compressed
Five of our resources carry an ETag: /llms.txt, /sitemap.xml, /robots.txt, /site.webmanifest and the hashed app bundle. Uncompressed, each answers a strong validator - "cd81798dca5470f0..." for llms.txt. Ask the same resource for gzip and the same digest comes back marked weak: W/"cd81798dca5470f0...". Same value, weaker claim, and the weak form is what a cache sees on every compressed response.
Content-Length disappears when the body is compressed
Every compressed answer we measured came back chunked, with no Content-Length header at all - on the app host and on the API host alike. Uncompressed, the same resources carry a length: /llms.txt 17,965, robots.txt 160, the app bundle 324,591, /api/health 410. A few API routes stay chunked even uncompressed, among them /api/plans, /api/voting and /api/products.
The PNG is left alone
icon-512.png came back at 18,385 bytes in all four variants, with no Content-Encoding on any of them. PNG is already compressed, so there is nothing to gain and the answer is left untouched - the one resource where asking for gzip changes absolutely nothing.
What this costs in practice
For a reader on the home page: 25,158 bytes uncompressed, 6,809 as brotli, 73% less. For the app bundle: 324,591 bytes uncompressed, 90,675 as brotli, 72% less. For a crawler fetching the sitemap: 4,046 bytes uncompressed, 475 as brotli, 88% less.
If you want to see these pages yourself, start with the home page and the guides index, then ask for them both ways:
curl -s -o /dev/null -w '%{size_download} bytes\n' https://app.onepassapps.com/ curl -s -o /dev/null -w '%{size_download} bytes\n' -H 'Accept-Encoding: gzip' https://app.onepassapps.com/ curl -s -o /dev/null -w '%{size_download} bytes\n' -H 'Accept-Encoding: br' https://app.onepassapps.com/ What I did not measure
This is one server in one region, so it describes what one vantage point received; we did not sample other edge locations. We did not open the browser DevTools network panel, so no claim here comes from a real page load. We did not compare HTTP/2 with HTTP/3, did not measure the cost of the extra response headers, did not measure client-side decompression time, and did not repeat the whole sweep on a second day. We sampled one guide page and one app page out of the twenty-two of each. The byte counts are what the server sent; what you receive depends on the path between you and it.
We will keep measuring and keep publishing the numbers.