[{"data":1,"prerenderedAt":1399},["ShallowReactive",2],{"content:\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard":3,"surroundings:\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard":1391},{"id":4,"title":5,"body":6,"description":1371,"extension":1372,"meta":1373,"navigation":1384,"path":1385,"seo":1386,"stem":1389,"__hash__":1390},"content\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Findex.md","Compression: Brotli & Zstandard",{"type":7,"value":8,"toc":1348},"minimark",[9,14,24,64,67,235,240,246,249,253,266,270,432,436,439,443,446,450,465,691,811,815,818,821,824,828,834,844,850,856,865,869,881,947,951,957,961,964,1039,1043,1052,1056,1059,1063,1066,1070,1080,1084,1105,1109,1135,1139,1171,1175,1187,1196,1205,1214,1229,1238,1247,1256,1265,1274,1278,1307,1311,1333,1338,1341,1344],[10,11,13],"h1",{"id":12},"compression-brotli-zstandard-for-every-text-response","Compression: Brotli & Zstandard for Every Text Response",[15,16,17,18,23],"p",{},"This topic is part of ",[19,20,22],"a",{"href":21},"\u002Fnetwork-protocol-optimization\u002F","Network & Server Response Optimization",". Text-based resources — HTML, CSS, JavaScript, JSON, SVG, XML, web app manifests — are highly compressible. A typical JavaScript bundle shrinks to 25–30% of its size with gzip and further with modern algorithms. Compression is one of the oldest and most effective web performance techniques, and yet audits routinely find uncompressed API responses, gzip-only CDNs, static assets compressed on every request at low levels, and fonts or images being pointlessly recompressed.",[15,25,26,27,31,32,35,36,39,40,44,45,48,49,52,53,48,56,59,60,63],{},"Browsers advertise the encodings they accept in the ",[28,29,30],"code",{},"Accept-Encoding"," request header (",[28,33,34],{},"gzip, deflate, br, zstd"," in current Chromium-based browsers), and servers choose one, indicating it with ",[28,37,38],{},"Content-Encoding",". ",[41,42,43],"strong",{},"Gzip"," is universal. ",[41,46,47],{},"Brotli"," (",[28,50,51],{},"br","), supported by all modern browsers over HTTPS, typically compresses text 15–25% better than gzip at comparable settings, with a built-in dictionary of common web strings that helps small files. ",[41,54,55],{},"Zstandard",[28,57,58],{},"zstd","), supported in Chromium-based browsers and Firefox, compresses much faster than Brotli at similar ratios for mid-range levels, which suits dynamic responses. ",[41,61,62],{},"Compression dictionary transport"," adds shared dictionaries, so updated resources can be sent as small differences from a previous version.",[15,65,66],{},"The right setup uses each where it fits best: maximum-level Brotli for static assets, compressed once at build time; moderate Brotli or zstd for dynamic responses compressed on the fly; gzip as a fallback; and shared dictionaries for frequently updated bundles.",[15,68,69],{},[70,71,77,78,77,85,77,89,77,92,77,101,77,107,77,113,77,120,77,124,77,129,77,132,77,136,77,139,77,143,77,147,77,151,77,153,77,157,77,161,77,164,77,166,77,169,77,172,77,176,77,178,77,181,77,186,77,189,77,191,77,194,77,197,77,201,77,203,77,206,77,208,77,210,77,212,77,214,77,217,77,221,77,223,77,225,77,227,77,230,77,232,77],"svg",{"viewBox":72,"width":73,"role":74,"ariaLabel":75,"style":76},"0 0 760 228","100%","img","Comparison of gzip, Brotli and Zstandard for web content on ratio, speed and support.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[79,80],"rect",{"className":81,"x":83,"y":83,"width":73,"height":73,"fill":84},[82],"svg-canvas","0","#ffffff",[86,87,88],"title",{},"Compression options compared",[90,91,75],"desc",{},[79,93],{"x":94,"y":94,"width":95,"height":96,"rx":97,"fill":98,"stroke":99,"style":100},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[102,103,88],"text",{"x":104,"y":105,"fill":99,"style":106},"28.0","34.0","font-size:16px;font-weight:700",[79,108],{"x":104,"y":109,"width":110,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},"56.0","145.1","30.0","fill-opacity:0.06;stroke-opacity:0.4",[102,114,119],{"x":115,"y":116,"fill":99,"style":117,"textAnchor":118},"38.0","75.5","font-size:12.5px;font-weight:700","start","Encoding",[79,121],{"x":122,"y":109,"width":123,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},"173.1","186.3",[102,125,128],{"x":126,"y":116,"fill":99,"style":117,"textAnchor":127},"266.3","middle","Ratio vs gzip",[79,130],{"x":131,"y":109,"width":123,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},"359.4",[102,133,135],{"x":134,"y":116,"fill":99,"style":117,"textAnchor":127},"452.6","Compress speed",[79,137],{"x":138,"y":109,"width":123,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},"545.7",[102,140,142],{"x":141,"y":116,"fill":99,"style":117,"textAnchor":127},"638.9","Browser support",[79,144],{"x":104,"y":145,"width":110,"height":111,"rx":83,"fill":98,"stroke":99,"style":146},"86.0","stroke-opacity:0.35",[102,148,150],{"x":115,"y":149,"fill":99,"style":117,"textAnchor":118},"105.5","gzip",[79,152],{"x":122,"y":145,"width":123,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},[102,154,156],{"x":126,"y":149,"fill":99,"style":155,"textAnchor":127},"font-size:12px","baseline",[79,158],{"x":131,"y":145,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},"#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[102,162,163],{"x":134,"y":149,"fill":99,"style":155,"textAnchor":127},"fast",[79,165],{"x":138,"y":145,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,167,168],{"x":141,"y":149,"fill":99,"style":155,"textAnchor":127},"universal",[79,170],{"x":104,"y":171,"width":110,"height":111,"rx":83,"fill":98,"stroke":99,"style":146},"116.0",[102,173,175],{"x":115,"y":174,"fill":99,"style":117,"textAnchor":118},"135.5","Brotli (br) level 11",[79,177],{"x":122,"y":171,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,179,180],{"x":126,"y":174,"fill":99,"style":155,"textAnchor":127},"15-25% smaller",[79,182],{"x":131,"y":171,"width":123,"height":111,"rx":83,"fill":183,"stroke":184,"style":185},"#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[102,187,188],{"x":134,"y":174,"fill":99,"style":155,"textAnchor":127},"very slow",[79,190],{"x":138,"y":171,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,192,193],{"x":141,"y":174,"fill":99,"style":155,"textAnchor":127},"all modern, HTTPS",[79,195],{"x":104,"y":196,"width":110,"height":111,"rx":83,"fill":98,"stroke":99,"style":146},"146.0",[102,198,200],{"x":115,"y":199,"fill":99,"style":117,"textAnchor":118},"165.5","Brotli level 4-6",[79,202],{"x":122,"y":196,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,204,205],{"x":126,"y":199,"fill":99,"style":155,"textAnchor":127},"10-20% smaller",[79,207],{"x":131,"y":196,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,209,163],{"x":134,"y":199,"fill":99,"style":155,"textAnchor":127},[79,211],{"x":138,"y":196,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,213,193],{"x":141,"y":199,"fill":99,"style":155,"textAnchor":127},[79,215],{"x":104,"y":216,"width":110,"height":111,"rx":83,"fill":98,"stroke":99,"style":146},"176.0",[102,218,220],{"x":115,"y":219,"fill":99,"style":117,"textAnchor":118},"195.5","Zstandard (zstd) 3-12",[79,222],{"x":122,"y":216,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,224,205],{"x":126,"y":219,"fill":99,"style":155,"textAnchor":127},[79,226],{"x":131,"y":216,"width":123,"height":111,"rx":83,"fill":159,"stroke":159,"style":160},[102,228,229],{"x":134,"y":219,"fill":99,"style":155,"textAnchor":127},"very fast",[79,231],{"x":138,"y":216,"width":123,"height":111,"rx":83,"fill":99,"stroke":99,"style":112},[102,233,234],{"x":141,"y":219,"fill":99,"style":155,"textAnchor":127},"Chromium, Firefox",[236,237,239],"h2",{"id":238},"the-metric-degradation-this-topic-addresses","The Metric Degradation This Topic Addresses",[15,241,242,243,245],{},"Uncompressed or poorly compressed text increases transfer time for HTML (delaying FCP and LCP), render-blocking CSS (delaying first paint), and JavaScript (delaying interactivity and increasing INP during startup). The effect is largest on slow connections, where every 100KB matters. Lighthouse's \"Enable text compression\" audit flags uncompressed text responses; the Network panel shows transfer size versus resource size and the ",[28,244,38],{}," of each response.",[15,247,248],{},"Compression also has a server-side cost: on-the-fly compression uses CPU per request, and maximum Brotli levels are too slow for dynamic responses — compressing a 200KB HTML response at level 11 can take tens of milliseconds, adding directly to TTFB. Choosing levels correctly avoids trading transfer time for server time.",[236,250,252],{"id":251},"prerequisites","Prerequisites",[254,255,256,260,263],"ul",{},[257,258,259],"li",{},"A list of resource types served, with sizes and whether they are static (build artefacts) or dynamic (rendered per request).",[257,261,262],{},"Access to server and CDN configuration.",[257,264,265],{},"The ability to add a build step for precompression.",[236,267,269],{"id":268},"_1-environment-setup-audit-current-encoding","1. Environment Setup: Audit Current Encoding",[271,272,277],"pre",{"className":273,"code":274,"language":275,"meta":276,"style":276},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","# Check which encoding each key resource gets.\nfor u in \u002F \u002Fcss\u002Fapp.css \u002Fjs\u002Fapp.js \u002Fapi\u002Fproducts?limit=20; do\n  printf '%-28s ' \"$u\"\n  curl -s -o \u002Fdev\u002Fnull -w '%{size_download}B ' -H 'Accept-Encoding: br, gzip, zstd' -D - \"https:\u002F\u002Fexample.com$u\" | grep -i '^content-encoding' | tr -d '\\r' || echo 'none'\ndone\n# trade-off: CDNs may vary encoding by client or cache state; test from several\n# regions and with browser-like headers.\n","bash","",[28,278,279,288,321,340,414,420,426],{"__ignoreMap":276},[280,281,284],"span",{"class":282,"line":283},"line",1,[280,285,287],{"class":286},"sjfSM","# Check which encoding each key resource gets.\n",[280,289,291,295,299,302,306,309,312,315,318],{"class":282,"line":290},2,[280,292,294],{"class":293},"sPARh","for",[280,296,298],{"class":297},"saISM"," u ",[280,300,301],{"class":293},"in",[280,303,305],{"class":304},"sZ8jY"," \u002F",[280,307,308],{"class":304}," \u002Fcss\u002Fapp.css",[280,310,311],{"class":304}," \u002Fjs\u002Fapp.js",[280,313,314],{"class":304}," \u002Fapi\u002Fproducts?limit=20",[280,316,317],{"class":297},"; ",[280,319,320],{"class":293},"do\n",[280,322,324,328,331,334,337],{"class":282,"line":323},3,[280,325,327],{"class":326},"sPXB4","  printf",[280,329,330],{"class":304}," '%-28s '",[280,332,333],{"class":304}," \"",[280,335,336],{"class":297},"$u",[280,338,339],{"class":304},"\"\n",[280,341,343,347,350,353,356,359,362,365,368,371,374,377,379,382,385,388,391,394,396,399,402,405,408,411],{"class":282,"line":342},4,[280,344,346],{"class":345},"sQw3B","  curl",[280,348,349],{"class":326}," -s",[280,351,352],{"class":326}," -o",[280,354,355],{"class":304}," \u002Fdev\u002Fnull",[280,357,358],{"class":326}," -w",[280,360,361],{"class":304}," '%{size_download}B '",[280,363,364],{"class":326}," -H",[280,366,367],{"class":304}," 'Accept-Encoding: br, gzip, zstd'",[280,369,370],{"class":326}," -D",[280,372,373],{"class":304}," -",[280,375,376],{"class":304}," \"https:\u002F\u002Fexample.com",[280,378,336],{"class":297},[280,380,381],{"class":304},"\"",[280,383,384],{"class":293}," |",[280,386,387],{"class":345}," grep",[280,389,390],{"class":326}," -i",[280,392,393],{"class":304}," '^content-encoding'",[280,395,384],{"class":293},[280,397,398],{"class":345}," tr",[280,400,401],{"class":326}," -d",[280,403,404],{"class":304}," '\\r'",[280,406,407],{"class":293}," ||",[280,409,410],{"class":326}," echo",[280,412,413],{"class":304}," 'none'\n",[280,415,417],{"class":282,"line":416},5,[280,418,419],{"class":293},"done\n",[280,421,423],{"class":282,"line":422},6,[280,424,425],{"class":286},"# trade-off: CDNs may vary encoding by client or cache state; test from several\n",[280,427,429],{"class":282,"line":428},7,[280,430,431],{"class":286},"# regions and with browser-like headers.\n",[236,433,435],{"id":434},"_2-capture-a-baseline","2. Capture a Baseline",[15,437,438],{},"Record transfer sizes for HTML, CSS, JS and API responses on key templates, plus server CPU usage and TTFB for dynamic responses.",[236,440,442],{"id":441},"_3-isolate-static-vs-dynamic","3. Isolate Static vs Dynamic",[15,444,445],{},"Static assets (hashed CSS, JS, SVG, fonts' CSS) can be compressed once at build time at the highest settings. Dynamic responses (SSR HTML, API JSON) must be compressed per request at moderate levels.",[236,447,449],{"id":448},"_4-apply-precompress-static-tune-dynamic","4. Apply: Precompress Static, Tune Dynamic",[15,451,452,453,456,457,460,461,464],{},"Generate ",[28,454,455],{},".br"," (and ",[28,458,459],{},".gz",", optionally ",[28,462,463],{},".zst",") files during the build and configure the server or CDN to serve them. Enable on-the-fly Brotli at level 4–6 or zstd at level 3–6 for dynamic content. Exclude already-compressed formats (images, video, WOFF2, archives).",[271,466,470],{"className":467,"code":468,"language":469,"meta":276,"style":276},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Build step: precompress text assets with Brotli 11 and gzip 9.\nimport { brotliCompressSync, gzipSync, constants } from 'node:zlib';\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { globSync } from 'glob';\nfor (const f of globSync('dist\u002F**\u002F*.{js,css,html,svg,json,xml,txt}')) {\n  const buf = readFileSync(f);\n  if (buf.length \u003C 1024) continue;   \u002F\u002F tiny files: not worth it\n  writeFileSync(`${f}.br`, brotliCompressSync(buf, { params: { [constants.BROTLI_PARAM_QUALITY]: 11, [constants.BROTLI_PARAM_SIZE_HINT]: buf.length } }));\n  writeFileSync(`${f}.gz`, gzipSync(buf, { level: 9 }));\n}\n\u002F\u002F trade-off: level 11 takes seconds for large bundles; run it once per build on\n\u002F\u002F hashed outputs, never per request.\n","javascript",[28,471,472,477,494,508,522,550,567,596,645,673,679,685],{"__ignoreMap":276},[280,473,474],{"class":282,"line":283},[280,475,476],{"class":286},"\u002F\u002F Build step: precompress text assets with Brotli 11 and gzip 9.\n",[280,478,479,482,485,488,491],{"class":282,"line":290},[280,480,481],{"class":293},"import",[280,483,484],{"class":297}," { brotliCompressSync, gzipSync, constants } ",[280,486,487],{"class":293},"from",[280,489,490],{"class":304}," 'node:zlib'",[280,492,493],{"class":297},";\n",[280,495,496,498,501,503,506],{"class":282,"line":323},[280,497,481],{"class":293},[280,499,500],{"class":297}," { readFileSync, writeFileSync } ",[280,502,487],{"class":293},[280,504,505],{"class":304}," 'node:fs'",[280,507,493],{"class":297},[280,509,510,512,515,517,520],{"class":282,"line":342},[280,511,481],{"class":293},[280,513,514],{"class":297}," { globSync } ",[280,516,487],{"class":293},[280,518,519],{"class":304}," 'glob'",[280,521,493],{"class":297},[280,523,524,526,528,531,534,537,541,544,547],{"class":282,"line":416},[280,525,294],{"class":293},[280,527,48],{"class":297},[280,529,530],{"class":293},"const",[280,532,533],{"class":326}," f",[280,535,536],{"class":293}," of",[280,538,540],{"class":539},"smZ65"," globSync",[280,542,543],{"class":297},"(",[280,545,546],{"class":304},"'dist\u002F**\u002F*.{js,css,html,svg,json,xml,txt}'",[280,548,549],{"class":297},")) {\n",[280,551,552,555,558,561,564],{"class":282,"line":422},[280,553,554],{"class":293},"  const",[280,556,557],{"class":326}," buf",[280,559,560],{"class":293}," =",[280,562,563],{"class":539}," readFileSync",[280,565,566],{"class":297},"(f);\n",[280,568,569,572,575,578,581,584,587,590,593],{"class":282,"line":428},[280,570,571],{"class":293},"  if",[280,573,574],{"class":297}," (buf.",[280,576,577],{"class":326},"length",[280,579,580],{"class":293}," \u003C",[280,582,583],{"class":326}," 1024",[280,585,586],{"class":297},") ",[280,588,589],{"class":293},"continue",[280,591,592],{"class":297},";   ",[280,594,595],{"class":286},"\u002F\u002F tiny files: not worth it\n",[280,597,599,602,604,607,610,613,616,619,622,625,628,631,634,637,640,642],{"class":282,"line":598},8,[280,600,601],{"class":539},"  writeFileSync",[280,603,543],{"class":297},[280,605,606],{"class":304},"`${",[280,608,609],{"class":297},"f",[280,611,612],{"class":304},"}.br`",[280,614,615],{"class":297},", ",[280,617,618],{"class":539},"brotliCompressSync",[280,620,621],{"class":297},"(buf, { params: { [constants.",[280,623,624],{"class":326},"BROTLI_PARAM_QUALITY",[280,626,627],{"class":297},"]: ",[280,629,630],{"class":326},"11",[280,632,633],{"class":297},", [constants.",[280,635,636],{"class":326},"BROTLI_PARAM_SIZE_HINT",[280,638,639],{"class":297},"]: buf.",[280,641,577],{"class":326},[280,643,644],{"class":297}," } }));\n",[280,646,648,650,652,654,656,659,661,664,667,670],{"class":282,"line":647},9,[280,649,601],{"class":539},[280,651,543],{"class":297},[280,653,606],{"class":304},[280,655,609],{"class":297},[280,657,658],{"class":304},"}.gz`",[280,660,615],{"class":297},[280,662,663],{"class":539},"gzipSync",[280,665,666],{"class":297},"(buf, { level: ",[280,668,669],{"class":326},"9",[280,671,672],{"class":297}," }));\n",[280,674,676],{"class":282,"line":675},10,[280,677,678],{"class":297},"}\n",[280,680,682],{"class":282,"line":681},11,[280,683,684],{"class":286},"\u002F\u002F trade-off: level 11 takes seconds for large bundles; run it once per build on\n",[280,686,688],{"class":282,"line":687},12,[280,689,690],{"class":286},"\u002F\u002F hashed outputs, never per request.\n",[15,692,693],{},[70,694,77,697,77,700,77,703,77,705,77,721,77,724,77,726,77,731,77,737,77,741,77,744,77,748,77,751,77,754,77,758,77,761,77,764,77,768,77,772,77,774,77,777,77,780,77,782,77,785,77,788,77,796,77,800,77,804,77,808,77],{"viewBox":695,"width":73,"role":74,"ariaLabel":696,"style":76},"0 0 760 232","Workflow from auditing encodings to precompressing static assets and tuning dynamic compression.",[79,698],{"className":699,"x":83,"y":83,"width":73,"height":73,"fill":84},[82],[86,701,702],{},"Compression rollout workflow",[90,704,696],{},[706,707,708],"defs",{},[709,710,716],"marker",{"id":711,"viewBox":712,"refX":669,"refY":713,"markerWidth":714,"markerHeight":714,"orient":715},"fa8c1eccff","0 0 10 10","5","7","auto-start-reverse",[717,718],"path",{"d":719,"fill":99,"style":720},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[79,722],{"x":94,"y":94,"width":95,"height":723,"rx":97,"fill":98,"stroke":99,"style":100},"230",[102,725,702],{"x":104,"y":105,"fill":99,"style":106},[79,727],{"x":104,"y":109,"width":728,"height":729,"rx":730,"fill":159,"stroke":159,"style":160},"208.0","55.0","6",[102,732,736],{"x":733,"y":734,"fill":99,"style":735,"textAnchor":127},"132.0","78.0","font-size:13px;font-weight:700","Audit",[102,738,740],{"x":733,"y":739,"fill":99,"style":155,"textAnchor":127},"96.0","encodings per type",[79,742],{"x":743,"y":109,"width":728,"height":729,"rx":730,"fill":159,"stroke":159,"style":160},"276.0",[102,745,747],{"x":746,"y":734,"fill":99,"style":735,"textAnchor":127},"380.0","Baseline",[102,749,750],{"x":746,"y":739,"fill":99,"style":155,"textAnchor":127},"bytes + CPU + TTFB",[79,752],{"x":753,"y":109,"width":728,"height":729,"rx":730,"fill":159,"stroke":159,"style":160},"524.0",[102,755,757],{"x":756,"y":734,"fill":99,"style":735,"textAnchor":127},"628.0","Split",[102,759,760],{"x":756,"y":739,"fill":99,"style":155,"textAnchor":127},"static vs dynamic",[79,762],{"x":753,"y":763,"width":728,"height":729,"rx":730,"fill":183,"stroke":184,"style":185},"155.0",[102,765,767],{"x":756,"y":766,"fill":99,"style":735,"textAnchor":127},"177.0","Precompress",[102,769,771],{"x":756,"y":770,"fill":99,"style":155,"textAnchor":127},"195.0","br 11 + gz 9",[79,773],{"x":743,"y":763,"width":728,"height":729,"rx":730,"fill":183,"stroke":184,"style":185},[102,775,776],{"x":746,"y":766,"fill":99,"style":735,"textAnchor":127},"Tune dynamic",[102,778,779],{"x":746,"y":770,"fill":99,"style":155,"textAnchor":127},"br 5 or zstd 3-6",[79,781],{"x":104,"y":763,"width":728,"height":729,"rx":730,"fill":159,"stroke":159,"style":160},[102,783,784],{"x":733,"y":766,"fill":99,"style":735,"textAnchor":127},"Verify",[102,786,787],{"x":733,"y":770,"fill":99,"style":155,"textAnchor":127},"headers + sizes",[282,789],{"x1":790,"y1":791,"x2":792,"y2":791,"stroke":99,"strokeWidth":793,"style":794,"markerEnd":795},"236.0","83.5","274.0","1.5","stroke-opacity:0.6","url(#fa8c1eccff)",[282,797],{"x1":798,"y1":791,"x2":799,"y2":791,"stroke":99,"strokeWidth":793,"style":794,"markerEnd":795},"484.0","522.0",[282,801],{"x1":756,"y1":802,"x2":756,"y2":803,"stroke":99,"strokeWidth":793,"style":794,"markerEnd":795},"111.0","153.0",[282,805],{"x1":753,"y1":806,"x2":807,"y2":806,"stroke":99,"strokeWidth":793,"style":794,"markerEnd":795},"182.5","486.0",[282,809],{"x1":743,"y1":806,"x2":810,"y2":806,"stroke":99,"strokeWidth":793,"style":794,"markerEnd":795},"238.0",[236,812,814],{"id":813},"deconstructing-compression-levels-and-windows","Deconstructing Compression Levels and Windows",[15,816,817],{},"Compression algorithms trade CPU time for size. Higher levels search harder for repeated patterns. For Brotli, levels 0–4 are fast, 5–9 are moderate, and 10–11 are very slow but produce the smallest output. Zstandard's levels run from 1 (very fast) to 19 (slow), with 20–22 \"ultra\" levels. Gzip levels 1–9 vary less in output size.",[15,819,820],{},"Window size matters too: it determines how far back the compressor can look for repeated sequences. Larger windows help large files but require more memory in the decoder; browsers cap acceptable window sizes for safety. For zstd on the web, the window is limited (8MB), which is fine for web resources.",[15,822,823],{},"For small responses — under about 1KB — compression overhead can outweigh savings; many servers skip compression below a minimum size. Brotli's built-in dictionary helps small text files more than gzip, which is one reason it does well on short HTML and JSON responses.",[236,825,827],{"id":826},"advanced-diagnostics-and-edge-cases","Advanced Diagnostics and Edge Cases",[15,829,830,833],{},[41,831,832],{},"Double compression."," Proxies compressing already-compressed responses, or applications compressing and then a CDN compressing again, waste CPU and can corrupt responses if headers are wrong.",[15,835,836,843],{},[41,837,838,839,842],{},"Missing ",[28,840,841],{},"Vary: Accept-Encoding","."," Without it, caches may serve a Brotli response to a client that cannot decode it.",[15,845,846,849],{},[41,847,848],{},"Streaming and compression."," Compression middleware can buffer output, breaking streaming SSR. Configure it to flush with each chunk.",[15,851,852,855],{},[41,853,854],{},"BREACH and compression of secrets."," Compressing responses that mix secrets (CSRF tokens) with user-controlled input can enable side-channel attacks; use per-request token masking.",[15,857,858,861,862,864],{},[41,859,860],{},"CDN normalisation."," Some CDNs normalise ",[28,863,30],{}," to a few buckets and may serve gzip when Brotli is possible unless configured.",[236,866,868],{"id":867},"validation-and-budgeting","Validation and Budgeting",[15,870,871,872,874,875,877,878,880],{},"In the Network panel, check that ",[28,873,38],{}," is ",[28,876,51],{}," (or ",[28,879,58],{},") for text resources in supporting browsers and gzip in others. Compare transfer sizes with your baseline. For dynamic responses, confirm TTFB did not increase. Budget compressed sizes for key bundles in CI, using Brotli sizes since that is what most users receive.",[882,883,884,900],"table",{},[885,886,887],"thead",{},[888,889,890,894,897],"tr",{},[891,892,893],"th",{},"Resource type",[891,895,896],{},"Recommended encoding",[891,898,899],{},"Level",[901,902,903,915,926,936],"tbody",{},[888,904,905,909,912],{},[906,907,908],"td",{},"Static JS, CSS, SVG (hashed)",[906,910,911],{},"Precompressed Brotli + gzip",[906,913,914],{},"br 11, gz 9",[888,916,917,920,923],{},[906,918,919],{},"SSR HTML",[906,921,922],{},"On-the-fly Brotli or zstd",[906,924,925],{},"br 4-6 \u002F zstd 3-6",[888,927,928,931,933],{},[906,929,930],{},"API JSON",[906,932,922],{},[906,934,935],{},"br 4-5 \u002F zstd 3",[888,937,938,941,944],{},[906,939,940],{},"Images, video, WOFF2",[906,942,943],{},"None (already compressed)",[906,945,946],{},"-",[236,948,950],{"id":949},"worked-example-a-saas-application","Worked Example: A SaaS Application",[15,952,953,954,956],{},"A SaaS dashboard served 1.9MB of JavaScript (uncompressed) through a CDN configured for gzip only, compressing on the fly at level 6; its API returned uncompressed JSON averaging 180KB per page. The team precompressed all hashed assets with Brotli 11 during the build, enabled Brotli level 5 for HTML and JSON at the CDN, and ensured ",[28,955,841],{}," was set. JavaScript transfer dropped from 560KB (gzip) to 455KB (Brotli 11); API JSON from 180KB to 24KB. On a 4G profile, dashboard load time improved by about 900ms and LCP p75 by 400ms. Origin CPU dropped too, because static assets were no longer compressed per request.",[236,958,960],{"id":959},"choosing-between-brotli-and-zstandard-for-dynamic-content","Choosing Between Brotli and Zstandard for Dynamic Content",[15,962,963],{},"For dynamic responses, the choice is about compression speed at a given ratio. Zstandard at levels 3–6 compresses several times faster than Brotli at comparable ratios, which matters on servers handling many requests or large HTML responses. Brotli at levels 4–5 is also fast and has universal modern browser support. A pragmatic approach: serve zstd to browsers that advertise it, Brotli to the rest of modern browsers, and gzip as the final fallback — if your server or CDN supports all three. If it supports only Brotli and gzip, Brotli at a moderate level is an excellent default.",[15,965,966],{},[70,967,77,970,77,973,77,976,77,978,77,981,77,983,77,990,77,997,77,1002,77,1006,77,1011,77,1015,77,1018,77,1022,77,1026,77,1030,77,1035,77],{"viewBox":968,"width":73,"role":74,"ariaLabel":969,"style":76},"0 0 760 194","Bar chart comparing CPU time to compress a 250KB HTML response with different algorithms and levels.",[79,971],{"className":972,"x":83,"y":83,"width":73,"height":73,"fill":84},[82],[86,974,975],{},"Compression time for a 250KB SSR HTML response",[90,977,969],{},[79,979],{"x":94,"y":94,"width":95,"height":980,"rx":97,"fill":98,"stroke":99,"style":100},"192",[102,982,975],{"x":104,"y":105,"fill":99,"style":106},[102,984,989],{"x":985,"y":986,"fill":99,"style":987,"textAnchor":988},"79.3","70.0","font-size:13px","end","gzip 6",[79,991],{"x":992,"y":109,"width":993,"height":994,"rx":995,"fill":159,"stroke":159,"style":996},"91.3","11.5","19","3","fill-opacity:0.55;stroke-opacity:0.9",[102,998,1001],{"x":999,"y":986,"fill":99,"style":1000},"108.9","font-size:12px;font-weight:600","4.2ms",[102,1003,1005],{"x":985,"y":1004,"fill":99,"style":987,"textAnchor":988},"101.0","zstd 3",[79,1007],{"x":992,"y":1008,"width":1009,"height":994,"rx":995,"fill":183,"stroke":184,"style":1010},"87.0","3.0","fill-opacity:0.7;stroke-opacity:0.9",[102,1012,1014],{"x":1013,"y":1004,"fill":99,"style":1000},"100.3","1.1ms",[102,1016,1017],{"x":985,"y":733,"fill":99,"style":987,"textAnchor":988},"Brotli 5",[79,1019],{"x":992,"y":1020,"width":1021,"height":994,"rx":995,"fill":159,"stroke":159,"style":996},"118.0","9.9",[102,1023,1025],{"x":1024,"y":733,"fill":99,"style":1000},"107.2","3.6ms",[102,1027,1029],{"x":985,"y":1028,"fill":99,"style":987,"textAnchor":988},"163.0","Brotli 11",[79,1031],{"x":992,"y":1032,"width":1033,"height":994,"rx":995,"fill":98,"stroke":99,"style":1034},"149.0","576.7","fill-opacity:0.7;stroke-opacity:0.35",[102,1036,1038],{"x":1037,"y":1028,"fill":99,"style":1000},"674.0","210ms",[236,1040,1042],{"id":1041},"compression-and-caching","Compression and Caching",[15,1044,1045,1046,1048,1049,1051],{},"Compressed variants must be cached separately per encoding. CDNs typically handle this automatically by keying on a normalised ",[28,1047,30],{}," value; when they do not, ",[28,1050,841],{}," instructs caches to store separate variants. A related consideration is whether the CDN or the origin compresses. Precompressed assets at the origin give the best ratio; CDN compression is convenient for dynamic content but may use lower levels. Check the CDN's configuration for which content types it compresses and at what level, and whether it passes through origin-compressed responses unchanged.",[236,1053,1055],{"id":1054},"shared-dictionaries-for-repeat-visits","Shared Dictionaries for Repeat Visits",[15,1057,1058],{},"Compression normally starts from scratch for every response. Compression dictionary transport lets the browser keep a previous response (for example, last week's JavaScript bundle) as a dictionary, and the server sends only what changed in the new version. For sites that deploy frequently, this can reduce repeat downloads of updated bundles by 80–95%. It requires server support for dictionary-based Brotli or zstd and appropriate headers, and currently works in Chromium-based browsers. It is the most significant advance in HTTP compression in years for sites with large, frequently updated JavaScript.",[236,1060,1062],{"id":1061},"what-compression-cannot-fix","What Compression Cannot Fix",[15,1064,1065],{},"Compression reduces transfer size, not the work the browser does afterwards. A 1MB JavaScript bundle compressed to 250KB still has to be decompressed, parsed and executed as 1MB of code, and on a mid-range phone that execution cost dominates. Likewise, a 300KB HTML document compressed to 40KB still produces a large DOM. Treat compression as the last step after reducing what you ship: code splitting, removing unused CSS and JavaScript, trimming markup, and avoiding oversized JSON payloads. A useful habit is to track both the compressed and uncompressed size of key bundles in CI; the compressed size predicts download time, while the uncompressed size predicts parse and execution cost.",[236,1067,1069],{"id":1068},"compression-for-apis-and-client-rendered-data","Compression for APIs and Client-Rendered Data",[15,1071,1072,1073,1075,1076,1079],{},"Single-page applications often move most of their bytes from HTML to JSON. API responses are frequently left uncompressed because they pass through application servers or API gateways with different defaults from the web server. JSON is highly repetitive (repeated keys, similar values) and compresses exceptionally well — 85–95% reductions are common for list responses. Make sure API gateways and backend-for-frontend services compress responses with Brotli or zstd, and that the client sends ",[28,1074,30],{}," (browsers do this automatically for ",[28,1077,1078],{},"fetch","). For very large, repeated payloads, consider whether the response shape itself can shrink: pagination, field selection and avoiding deeply nested duplicate objects often save more than any algorithm.",[236,1081,1083],{"id":1082},"monitoring-compression-in-production","Monitoring Compression in Production",[15,1085,1086,1087,1089,1090,1092,1093,1096,1097,1100,1101,1104],{},"Compression silently breaks during infrastructure changes: a new CDN rule, a proxy upgrade, a framework middleware change. Add a synthetic check that requests key resources with a browser-like ",[28,1088,30],{}," header and asserts the expected ",[28,1091,38],{}," and an upper bound on transferred bytes. In RUM, Resource Timing exposes ",[28,1094,1095],{},"encodedBodySize"," and ",[28,1098,1099],{},"decodedBodySize"," for same-origin resources (and cross-origin ones with ",[28,1102,1103],{},"Timing-Allow-Origin","); a ratio close to 1 for a text resource means it arrived uncompressed. Alerting on that ratio for scripts and stylesheets catches regressions within hours.",[236,1106,1108],{"id":1107},"a-rollout-plan","A Rollout Plan",[1110,1111,1112,1115,1118,1123,1126,1129,1132],"ol",{},[257,1113,1114],{},"Audit encodings for every resource type on key templates.",[257,1116,1117],{},"Add precompression (Brotli 11, gzip 9) to the build for static text assets.",[257,1119,1120,1121,842],{},"Configure the server or CDN to serve precompressed files and set ",[28,1122,841],{},[257,1124,1125],{},"Enable on-the-fly Brotli (4–6) or zstd (3–6) for HTML and JSON.",[257,1127,1128],{},"Exclude already-compressed types from compression.",[257,1130,1131],{},"Consider dictionary transport for large, frequently updated bundles.",[257,1133,1134],{},"Add CI checks for encoding headers and compressed bundle budgets.",[236,1136,1138],{"id":1137},"common-pitfalls","Common Pitfalls",[254,1140,1141,1147,1153,1159,1165],{},[257,1142,1143,1146],{},[41,1144,1145],{},"gzip-only CDN configuration."," Leaves 15–25% savings unused.",[257,1148,1149,1152],{},[41,1150,1151],{},"Brotli 11 on the fly."," Adds tens of milliseconds to TTFB per response.",[257,1154,1155,1158],{},[41,1156,1157],{},"Uncompressed API responses."," JSON compresses extremely well; often forgotten.",[257,1160,1161,1164],{},[41,1162,1163],{},"Compressing images and fonts."," Wasted CPU with no size benefit.",[257,1166,1167,1170],{},[41,1168,1169],{},"Compression middleware that breaks streaming."," Buffering hides the benefits of streaming SSR.",[236,1172,1174],{"id":1173},"faq","FAQ",[1176,1177,1180,1184],"details",{"className":1178},[1179],"faq-item",[1181,1182,1183],"summary",{},"Is Brotli supported everywhere?",[15,1185,1186],{},"All modern browsers support Brotli over HTTPS. Keep gzip as a fallback for older clients and some bots.",[1176,1188,1190,1193],{"className":1189},[1179],[1181,1191,1192],{},"Which Brotli level should I use?",[15,1194,1195],{},"Level 11 for static assets compressed at build time; level 4–6 for dynamic responses compressed per request.",[1176,1197,1199,1202],{"className":1198},[1179],[1181,1200,1201],{},"Should I enable Zstandard?",[15,1203,1204],{},"If your server or CDN supports it, zstd is a good choice for dynamic responses to supporting browsers because it compresses quickly. Keep Brotli and gzip for others.",[1176,1206,1208,1211],{"className":1207},[1179],[1181,1209,1210],{},"Does compression help images?",[15,1212,1213],{},"No. Formats like JPEG, PNG, WebP, AVIF and video are already compressed. SVG is text and does benefit.",[1176,1215,1217,1220],{"className":1216},[1179],[1181,1218,1219],{},"How do I know if my CDN uses Brotli?",[15,1221,1222,1223,1225,1226,1228],{},"Check the ",[28,1224,38],{}," response header for text resources in a modern browser. If it says ",[28,1227,150],{},", Brotli is not enabled or not passed through.",[1176,1230,1232,1235],{"className":1231},[1179],[1181,1233,1234],{},"Does compression increase TTFB?",[15,1236,1237],{},"On-the-fly compression adds a little CPU time. At moderate levels it is a few milliseconds, more than repaid by faster transfer. High levels on the fly can add noticeably.",[1176,1239,1241,1244],{"className":1240},[1179],[1181,1242,1243],{},"Should HTML be precompressed?",[15,1245,1246],{},"Static HTML from a static site generator can be precompressed like other assets. Server-rendered HTML must be compressed per request.",[1176,1248,1250,1253],{"className":1249},[1179],[1181,1251,1252],{},"How much does compression improve LCP?",[15,1254,1255],{},"It depends on how much of the LCP path is text transfer. For pages where render-blocking CSS and large HTML dominate, moving from gzip to Brotli typically improves LCP by tens to a couple of hundred milliseconds on mobile; going from no compression to Brotli can save far more.",[1176,1257,1259,1262],{"className":1258},[1179],[1181,1260,1261],{},"Should compression happen at the origin or at the CDN?",[15,1263,1264],{},"Static assets are best precompressed at the origin at maximum levels. Dynamic responses can be compressed at either; compressing at the CDN offloads CPU from the origin, while compressing at the origin lets you choose algorithms and levels precisely.",[1176,1266,1268,1271],{"className":1267},[1179],[1181,1269,1270],{},"Is gzip still needed?",[15,1272,1273],{},"Yes, as a fallback for clients that do not advertise Brotli or zstd, including some tools and crawlers.",[236,1275,1277],{"id":1276},"guides-in-this-topic","Guides in This Topic",[254,1279,1280,1287,1294,1301],{},[257,1281,1282,1286],{},[19,1283,1285],{"href":1284},"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fenabling-brotli-on-nginx-and-cdns\u002F","Enabling Brotli on nginx and CDNs"," — server and CDN configuration.",[257,1288,1289,1293],{},[19,1290,1292],{"href":1291},"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fzstandard-content-encoding-for-the-web\u002F","Zstandard Content-Encoding for the web"," — when and how to serve zstd.",[257,1295,1296,1300],{},[19,1297,1299],{"href":1298},"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fprecompressing-static-assets-at-build-time\u002F","Precompressing static assets at build time"," — maximum compression without runtime cost.",[257,1302,1303,1306],{},[19,1304,62],{"href":1305},"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fcompression-dictionary-transport\u002F"," — sending only what changed.",[236,1308,1310],{"id":1309},"related","Related",[254,1312,1313,1319,1326],{},[257,1314,1315,1318],{},[19,1316,1317],{"href":21},"Network & server response optimization"," — the full network picture.",[257,1320,1321,1325],{},[19,1322,1324],{"href":1323},"\u002Fnetwork-protocol-optimization\u002Fstreaming-ssr-and-early-flush\u002Fstreaming-html-through-cdns-and-proxies\u002F","Streaming HTML through CDNs and proxies"," — compression that does not buffer.",[257,1327,1328,1332],{},[19,1329,1331],{"href":1330},"\u002Fjavascript-bundle-optimization-code-splitting\u002F","JavaScript bundle optimization"," — shipping fewer bytes before compressing them.",[1334,1335,1337],"script",{"type":1336},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"Compression: Brotli & Zstandard for Every Text Response\",\n  \"description\": \"How HTTP compression works, how Brotli and Zstandard compare with gzip, and how to configure compression for static and dynamic responses across servers and CDNs.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Environment Setup: Audit Current Encoding\",\n      \"text\": \"Environment Setup: Audit Current Encoding\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Capture a Baseline\",\n      \"text\": \"Record transfer sizes for HTML, CSS, JS and API responses on key templates, plus server CPU usage and TTFB for dynamic responses.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Isolate Static vs Dynamic\",\n      \"text\": \"Static assets (hashed CSS, JS, SVG, fonts' CSS) can be compressed once at build time at the highest settings.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Apply: Precompress Static, Tune Dynamic\",\n      \"text\": \"Generate .br (and .gz, optionally .zst) files during the build and configure the server or CDN to serve them.\"\n    }\n  ]\n}\n",[1334,1339,1340],{"type":1336},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"Compression: Brotli & Zstandard for Every Text Response\",\n  \"description\": \"How HTTP compression works, how Brotli and Zstandard compare with gzip, and how to configure compression for static and dynamic responses across servers and CDNs.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002F\"\n  }\n}\n",[1334,1342,1343],{"type":1336},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Network & Server Response Optimization\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fnetwork-protocol-optimization\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Compression: Brotli & Zstandard\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002F\"\n    }\n  ]\n}\n",[1345,1346,1347],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}",{"title":276,"searchDepth":290,"depth":290,"links":1349},[1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370],{"id":238,"depth":290,"text":239},{"id":251,"depth":290,"text":252},{"id":268,"depth":290,"text":269},{"id":434,"depth":290,"text":435},{"id":441,"depth":290,"text":442},{"id":448,"depth":290,"text":449},{"id":813,"depth":290,"text":814},{"id":826,"depth":290,"text":827},{"id":867,"depth":290,"text":868},{"id":949,"depth":290,"text":950},{"id":959,"depth":290,"text":960},{"id":1041,"depth":290,"text":1042},{"id":1054,"depth":290,"text":1055},{"id":1061,"depth":290,"text":1062},{"id":1068,"depth":290,"text":1069},{"id":1082,"depth":290,"text":1083},{"id":1107,"depth":290,"text":1108},{"id":1137,"depth":290,"text":1138},{"id":1173,"depth":290,"text":1174},{"id":1276,"depth":290,"text":1277},{"id":1309,"depth":290,"text":1310},"How HTTP compression works, how Brotli and Zstandard compare with gzip, and how to configure compression for static and dynamic responses across servers and CDNs.","md",{"slug":1374,"type":1375,"breadcrumb":1376,"datePublished":1383,"dateModified":1383},"compression-brotli-and-zstandard","topic",[1377,1380,1381],{"name":1378,"url":1379},"Home","\u002F",{"name":22,"url":21},{"name":5,"url":1382},"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002F","2026-10-06",true,"\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard",{"title":1387,"description":1388},"Brotli and Zstandard Compression for Faster Pages","Compress HTML, CSS, JS and JSON with Brotli and Zstandard: choose levels for static vs dynamic responses, precompress assets, and use dictionaries for updates.","network-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Findex","2-0aKV2qSwQvnTnW9LMzb1jIwtorLgjAcs3CaWQt3z4",[1392,1395],{"title":22,"path":1393,"stem":1394,"children":-1},"\u002Fnetwork-protocol-optimization","network-protocol-optimization\u002Findex",{"title":1396,"path":1397,"stem":1398,"children":-1},"Compression Dictionary Transport","\u002Fnetwork-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fcompression-dictionary-transport","network-protocol-optimization\u002Fcompression-brotli-and-zstandard\u002Fcompression-dictionary-transport\u002Findex",1791308070229]