Server-Side and Client-Side Detection Compared
Detection can happen on the server before a response is composed, or in the browser once script runs. The two answer different questions and fail in different ways.
Server-side decides before anything is sent
A server inspecting request headers can choose markup, assets and layout before the first byte leaves. Nothing is sent and then replaced.
This avoids the visible correction that client-side adaptation can produce, where a page renders one way and rearranges once script has run.
The cost is that the server only knows what the request carried, which after header reduction is coarse and may lack hints entirely on a first visit.
Client-side can test rather than infer
In the browser, code can check whether a capability exists rather than guessing from an identity. The answer is direct and does not depend on any dataset.
It can also measure things no header describes, such as the actual viewport, available input methods or whether a feature works in practice.
The limitation is timing. Script runs after the document has begun loading, so decisions affecting the initial render must already have been made.
Caching is where the difference bites
A server that varies its response on client characteristics must tell caches it has done so, which fragments the cache by whatever it varied on.
Varying on the full user agent effectively disables shared caching, because the number of distinct values is enormous.
Client-side adaptation keeps one cacheable response and adapts after delivery. For heavily cached sites that is often the deciding factor.
Hybrid approaches are the common outcome
A workable pattern serves one cacheable response with coarse server-side decisions, then refines client-side where refinement is worth the disruption.
Coarse decisions are those the low-entropy hints support: a mobile flag, a platform family, a brand. These narrow the response without fragmenting caches badly.
Anything finer belongs after delivery, where testing beats inference and no cache entry is created for it.
Choosing by what the decision affects
If the decision changes markup structure, it usually belongs server-side. If it changes behaviour or enhancement, it belongs client-side.
If it changes a downloadable artefact, it belongs server-side but should offer an explicit alternative, since a wrong choice is a hard failure.
Stating what a wrong answer costs, before choosing where to detect, resolves most of these questions without further argument.