# Personalizing Sanity content without blowing up GROQ/CDN caching

Asked by Zhang Wei on 2025-02-11. Tags: sanity, groq, caching, performance.

We run a marketplace on Sanity and lean heavily on the CDN for GROQ query
performance. Nearly every content request is a cache hit today and our page
latency budget depends on that.

My worry with adding personalization: if queries start carrying per-user
context, every request becomes a cache miss and we pay origin latency on
every page view. That would be a regression we cant accept.

How does the Croct integration deal with this? Does user context end up in
the GROQ queries, or does variant resolution happen somewhere else entirely?

## 2 answers

### Accepted answer from Croct Bot (2025-02-11)

User context never enters your GROQ queries. The overlay model keeps the
two concerns separate by design:

1. [Sanity](https://docs.croct.com/immersion/integrations/cms/sanity) keeps serving your default content exactly as today. Queries stay
   user-agnostic, so they remain fully cacheable by Sanity's CDN.
2. Croct resolves which variant applies to each visitor on its own side.
   Your frontend asks Croct for the content of a slot, and the audience
   evaluation happens per visitor in Croct's infrastructure, not in your
   content queries.

In other words, personalization is resolved per slot per visitor, while
your Sanity data layer stays shared and cacheable. If no experience matches
a visitor, the slot falls back to the regular Sanity content.

On the latency of the Croct call itself: end-to-end response times are
under 90 milliseconds at P95, and the SDKs let you define fallback content
so a slow or failed fetch degrades to your default content. See the
[content fetching documentation](https://docs.croct.com/explanation/content/fallback-content) for the fallback
options per SDK.

### Answer from renata_alv (2025-02-12)

Running this combination in production on a content site, can confirm the
cache behavior in practice. Our GROQ hit rate did not move after rollout
because the queries are byte-identical for every visitor, all the
per-visitor variation comes through the slot fetch.

One implementation tip: resolve the slot content in parallel with your
Sanity fetch rather than sequentially, so the personalization call does not
add to the critical path. With both running concurrently the slower of the
two determines latency, and in our metrics that is usually still the
Sanity round trip on cache misses.

#### Reply from Zhang Wei (2025-02-13)

The parallel fetch tip is exactly what I needed, thanks. Prototyped it
yesterday and the p95 impact on our side is within noise.
