Compression Dictionary Transport: Download Only What Changed

This guide is part of Compression: Brotli & Zstandard, within Network & Server Response Optimization. When you deploy a new version of a JavaScript bundle, its hashed URL changes and every returning visitor downloads the whole file again, even though most of the code is identical to the version they already have. For sites that deploy daily, this means returning users repeatedly download hundreds of kilobytes they already hold.

Compression dictionary transport fixes this. A response can declare itself usable as a dictionary for future requests matching a URL pattern (Use-As-Dictionary). On the next request matching that pattern, the browser advertises the dictionary it has (Available-Dictionary, a hash), and the server can respond with the new file compressed using the old file as a dictionary — Brotli (dcb) or Zstandard (dcz). Because the dictionary already contains almost everything, the compressed delta is tiny: often 80–95% smaller than normal Brotli compression of the new version.

Delta compression with a shared dictionary Sequence showing a browser storing a bundle as a dictionary and later receiving a new version as a small delta. Delta compression with a shared dictionary Browser Server GET /js/app.v1.js app.v1 + Use-As-Dictionary GET /js/app.v2.js + Available-Dictionary dcb delta (small)

Rapid Diagnosis

  • Check how often you deploy and how much of each bundle changes per release.
  • Measure returning-visitor JS downloads in RUM (transfer size for scripts on repeat visits after deploys).
  • Check browser support in your audience (Chromium-based browsers currently).
  • Check server or CDN support for dictionary-compressed responses.

Root Cause Analysis

1. Hashed filenames defeat caching on change. Any change produces a new URL and full download.

2. Frequent deploys. Each deploy re-downloads large unchanged portions.

3. Large bundles. The larger the bundle, the more delta compression saves.

4. Shared structure across pages. HTML pages share most of their markup; a dictionary of common HTML can shrink every page.

Step-by-Step Resolution

1. Mark bundles as dictionaries

http
HTTP/1.1 200 OK
Content-Type: text/javascript
Cache-Control: public, max-age=31536000, immutable
Use-As-Dictionary: match="/js/app.*.js"

The browser stores the response as a dictionary for future requests whose URL matches the pattern.

2. Serve deltas when the browser has a dictionary

When a request includes Available-Dictionary: :<sha-256 base64>: and Accept-Encoding includes dcb or dcz, look up the previous version by hash, and serve a precomputed delta.

bash
# Build step: precompute a Brotli delta from the previous release.
brotli -q 11 --dictionary=releases/app.v1.js -o dist/js/app.v2.js.dcb-from-v1 dist/js/app.v2.js
# Hash of the dictionary (what the browser sends in Available-Dictionary).
openssl dgst -sha256 -binary releases/app.v1.js | base64
# trade-off: keeping deltas for several previous versions improves hit rates but
# multiplies build artefacts; most sites keep the last 2-5 releases.

Responses must include Content-Encoding: dcb (or dcz) and Vary: Accept-Encoding, Available-Dictionary.

3. Fall back cleanly

If the dictionary hash is unknown, serve normal Brotli or gzip. The browser handles both.

4. Consider custom dictionaries for HTML

A separate dictionary resource (declared via <link rel="compression-dictionary" href="/dict/html.dict">) built from common markup can shrink every HTML page, including first navigations to new pages after the dictionary has been fetched.

Returning-visitor download of an updated 640KB bundle Bar chart comparing the transfer size of an updated JavaScript bundle with gzip, Brotli and Brotli delta compression. Returning-visitor download of an updated 640KB bundle gzip 182KB Brotli 11 154KB Brotli delta from previous version 11KB

Verification

In Chrome DevTools, the Network panel shows Content-Encoding: dcb or dcz for delta-compressed responses, and the transfer size is far smaller than the resource size. The Available-Dictionary request header appears on matching requests. In RUM, compare script transfer sizes for returning visitors after a deploy with the pre-dictionary baseline.

Worked Example: A Web App With Daily Deploys

A collaborative editing app shipped a 1.1MB (uncompressed) main bundle and deployed every weekday. Returning users downloaded about 290KB of Brotli-compressed JavaScript after each deploy. The team added Use-As-Dictionary to the bundle and generated Brotli deltas from the previous three releases at build time, served by an edge function that matched Available-Dictionary hashes. For Chromium users (78% of traffic), post-deploy bundle downloads fell to 14–40KB depending on the size of the release. Time to interactive for returning users on the first visit after a deploy improved by about 600ms on mid-range Android devices.

Deploying delta compression Steps to roll out compression dictionary transport for versioned bundles. Deploying delta compression Mark Use-As-Dictionar y Keep releases last 2-5 versions Build deltas dcb / dcz per pair Serve match Available-Dictiona ry Fallback plain br or gzip

Choosing Dictionaries and Match Patterns

The match pattern decides which future requests can use a dictionary. For versioned bundles, a pattern like /js/app.*.js matches every future version of the same bundle. Keep patterns specific to avoid using an unrelated file as a dictionary (which only wastes the opportunity; correctness is preserved by the hash check). For many small chunks, delta compression helps less per file; consider fewer, larger stable chunks for the code that changes rarely. Dictionaries are stored per origin and are partitioned like caches, and browsers may evict them; always keep normal compression as the fallback.

Measuring the Benefit

The benefit appears only for returning visitors after a deploy, so measure that cohort specifically. In RUM, record the transferred size of the main bundle along with whether the response used dcb or dcz (visible via encodedBodySize being much smaller than usual) and the time since the last deploy. Compare first-visit-after-deploy sessions before and after enabling dictionaries. Server-side, log the share of requests that arrive with an Available-Dictionary header and the share you could serve a delta for; a low match rate usually means too few previous versions are kept or the match pattern is too narrow.

Common Mistakes

  • Missing Vary on Available-Dictionary. Caches could serve a delta to a client without the dictionary.
  • Unsafe deltas from cross-origin dictionaries. Dictionaries must be same-origin (or CORS-readable) to prevent data leaks.
  • No fallback. Clients without the dictionary must receive normal compression.
  • Keeping too few old versions. Users who skip several releases fall back to full downloads.

Edge Cases

CDN caching of deltas. The cache key must include the dictionary hash; some CDNs support this natively, others need edge logic.

Privacy. Dictionaries are partitioned and cleared with site data, like cookies and caches.

Service workers. Requests from service workers can also use dictionaries, but test the full flow.

Very small changes. Even a one-line change produces a new hash; deltas handle it efficiently.

FAQ

Which browsers support compression dictionary transport?

Chromium-based browsers currently support it. Other browsers ignore the headers and receive normal compression.

What are dcb and dcz?

Content encodings for dictionary-compressed Brotli (dcb) and dictionary-compressed Zstandard (dcz).

Is this the same as SDCH?

It is a successor in spirit. SDCH was an older Chrome experiment that was removed; the new standard addresses its security and privacy issues.

Does it help first-time visitors?

Not for delta updates, since they have no previous version. Custom dictionaries for HTML can help subsequent pages within a first visit.

How do I generate deltas?

Use Brotli or zstd command-line tools or libraries with the previous version as a dictionary, at build time for static assets.

Can CDNs do this automatically?

Some CDNs have begun offering dictionary compression features. Check your provider; otherwise, edge functions can implement it.

Is it secure?

The standard restricts dictionaries to same-origin or CORS-readable resources and uses hashes to ensure the right dictionary is used, addressing the issues of earlier approaches.

Do dictionaries use extra storage on the device?

Yes, the dictionary is stored like a cached response. Browsers manage this storage and evict dictionaries like other cache entries.