# Best caching strategy when only some Hydrogen routes are personalized?

Asked by Emily Chen on 2026-03-10. Tags: shopify, hydrogen, oxygen, caching, best-practices.

Planning the rollout of Croct on our DTC storefront and trying to decide the
caching strategy upfront. The marketing pages (home, collections, editorial) serve
the same content to everyone and I want them to stay on the public edge cache. The
account area and a new personalized offers route would resolve content per request.

Is "cache the anonymous routes, keep the personalized ones dynamic" the right
mental model, or is there a smarter split people use? Also curious what the
per-request cost looks like in practice, we care a lot about LCP on mobile

## 1 answer

### Accepted answer from matheus.lima (2026-03-11)

That mental model is exactly right, and it is what we settled on after some
trial and error. Routes that serve the same content to everyone stay publicly
cacheable, and routes whose loaders resolve personalized content stay dynamic.
There is no clever middle ground worth chasing, a personalized document simply
cannot be shared between users.

What makes the split cheap in practice is that only the document render is per
request. Sub-page resources like assets, images, and product data from the
Storefront API keep their own cache strategies either way, so a dynamic route is
not a fully uncached route. Our personalized offers page loads within a few
dozen ms of the cached pages.

On the content fetch itself, Croct requests are built for request-time
resolution, end-to-end under 90 milliseconds at P95, and it runs inside the
loader alongside your storefront queries, so it overlaps with work you were
doing anyway rather than stacking on top of it.

One tip: decide the split per route at planning time like you are doing, not
after the fact. Retrofitting dynamic rendering onto a route that was designed
around a cached document is where the pain lives.

#### Reply from Emily Chen (2026-03-11)

Super helpful, especially the point about the loader fetch overlapping the
storefront queries. Going with this split, thanks.
