A support dashboard once treated a User-Agent string as a compact identity card. One value fed the browser label, operating-system filter, mobile split, and a set of routing rules. That arrangement was convenient until the same reduced Chrome string began producing identical-looking records for devices that needed different support paths. The problem was not that the header became shorter. The problem was that the decision trail disappeared with the detail.
Ask what decision needs the fact
Browser identity is not one question. A download page may need browser family and major version. A media issue may need mobile status and platform. A compatibility investigation may need the high-entropy platform version, the request path, and whether the browser actually returned the hint. Recording every available value for every request creates more retention and cache variation without proving that the result is more useful.
Write the decision beside the field before requesting it. For example, “choose the desktop installer” needs a stable platform category, while “show a warning for Chromium 120 and lower” needs a major version. If no product behavior changes when a field is missing, it probably does not belong in the collection model.
A request is not the same as a response
Client Hints are negotiated. The server can advertise an acceptable hint with Accept-CH, but the browser, permission state, cache, and request sequence still determine what arrives. An illustrative exchange looks like this:
HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Platform-Version, Sec-CH-UA-Model
Vary: Sec-CH-UA-Platform-Version, Sec-CH-UA-ModelSec-CH-UA: "Chromium";v="124", "Not.A/Brand";v="99" Sec-CH-UA-Mobile: ?0 Sec-CH-UA-Platform: "Windows" ~~~
The Vary header is not decoration. If a CDN serves a response generated for one hint set to another client, the site can make a wrong compatibility decision even though the parser is correct. Record whether the hint was sent, inferred, or missing. That status is often more valuable than a guessed replacement value.
Keep the evidence together
Our preferred observation has four layers: the reduced User-Agent, the low-entropy hints, the hints that were requested, and the decision made from them. A compact JSON record can make the distinction visible.
{
"ua": "Mozilla/5.0 ... Chrome/124.0.0.0 Safari/537.36",
"hints": { "platform": "Windows", "mobile": false },
"requested": ["platform-version"],
"received": [],
"classification": "desktop-chromium",
"confidence": "limited"
}The ellipsis in this example is intentional. A compatibility record does not need to preserve a complete raw header forever when the decision only needs a normalized family and major version. If raw samples are retained for debugging, define a short retention window and remove account tokens, cookies, and query values before sharing them.
A cache failure can look like a parser failure
Consider a two-step page: the first navigation receives the reduced string, the second request receives platform version, and a cached HTML response contains the first visitor’s installer link. A support engineer may see a valid Windows hint and still receive the wrong page because the cache key omitted the hint that changed the decision. The investigation should compare request headers, response headers, cache status, and the final link, in that order.
The useful test fixture covers more than one browser family. Include Chromium with hints, Chromium without hints, Firefox, Safari, an Android WebView, and a client that sends a malformed or empty value. The expected result should distinguish “not a Chromium client” from “Chromium detail unavailable.” Treating both as unknown hides the boundary that matters.
Test the cache boundary
Add a cache variation to the fixture. Request the page once without a platform hint, once with a Windows hint, and once with the hint absent again. Compare the response body, cache status, Vary header, and chosen link. An illustrative failure is a Windows installer being served to the second request after the first response was cached under a key that ignored the hint. The parser is correct in every request; the cache decision is wrong.
Keep the cache key no wider than the decision requires. If the page only varies by a coarse platform bucket, do not vary on a full model or version. Every additional variation creates more cache entries and more ways for a stale response to survive. Document the fallback when a hint arrives too late for the first navigation, and test a cold cache as well as a warm cache.
Keep the fallback boring
The safest missing-hint path is usually a usable generic page, not a guess. A user can choose a download manually, while a support engineer can see that the platform detail was unavailable. Avoid redirect loops that repeatedly request a high-entropy hint or a page that silently assumes Windows because the old regex did. A field marked unavailable is easier to explain than an incorrect installer.
The migration rule
Move consumers one at a time. Replace operating-system regexes with a bounded field, compare the old and new classifications in a shadow column, and inspect disagreements before changing a production dashboard. Keep a fallback for clients that cannot send hints. Most importantly, let “not available” remain an honest answer. A smaller evidence trail can still support excellent decisions when every inference states what it used and what it did not know.