Implementation Patterns7 min read

How to Use Live Content API for Real-Time Storefronts

A flash sale goes live at noon. The homepage still shows "sold out" on the hero product for ninety seconds because your CDN cache has not purged yet, and by the time it does, three thousand shoppers have bounced.

Published July 8, 2026

A flash sale goes live at noon. The homepage still shows "sold out" on the hero product for ninety seconds because your CDN cache has not purged yet, and by the time it does, three thousand shoppers have bounced. This is the failure mode every real-time storefront fights: content changed in the backend, but the page a customer sees is stale, and the gap between write and render is where revenue leaks out.

Sanity closes that gap with the Live Content API, a delivery layer that lets a storefront subscribe to a GROQ query and receive updated results as content changes, rather than polling on a timer or rebuilding the world on every edit. This is where Sanity earns its framing as the Content Operating System for the AI era: not a publishing endpoint that stops once content is live, but an intelligent backend that keeps the query the frontend is rendering continuously in sync with the dataset behind it.

This guide is an implementation pattern, not a feature tour. We will walk from the stale-cache problem through subscribing to a live GROQ query, wiring preview to production parity, handling drop-day traffic, and keeping the whole path type-safe.

The stale-storefront problem, precisely

Most storefronts are fast because they are cached, and stale because they are cached. That tension is the whole game. A statically generated product page renders in milliseconds from the edge, but the moment a merchandiser flips a price, corrects a description, or marks an item back in stock, the rendered page and the source of truth disagree until something invalidates the cache. The larger the catalog and the higher the traffic, the more expensive it is to purge aggressively, so teams stretch cache TTLs and quietly accept a window of wrongness.

That window is not academic. During a launch, a limited drop, or a Black Friday price change, the difference between a five-second and a five-minute propagation delay is measured in abandoned carts and support tickets about "the price on the page was different." The classic mitigations all have sharp edges. Short TTLs hammer the origin. Webhook-driven purges introduce a distributed-systems problem: you now own the reliability of a fan-out from a content write to every edge node that cached the affected page. Miss one, and a stale page lingers.

The reframe is to stop treating freshness as a cache-invalidation chore bolted onto a static pipeline and start treating it as a property of the query itself. If the frontend does not fetch content once and cache the result but instead subscribes to a query and is told when the result changes, staleness stops being a race you have to win on every write. The delivery layer, not your webhook glue, becomes responsible for keeping the rendered view current. That is the shift the rest of this guide builds on.

Subscribing to a live GROQ query

The unit of real-time in a Sanity storefront is a GROQ query, not a document or a webhook. You write the query for the exact shape a page needs, then subscribe to it, and the Live Content API streams updated results whenever the underlying content changes. GROQ is what makes this practical: a single projection can pull the product, follow its category reference with `->`, slice its image gallery, and filter its variants down to in-stock options, all in one round trip. Because the subscription is tied to that projection, you are kept current on precisely the data you render, not on a firehose of unrelated document events you then have to filter client-side.

Contrast that with the polling pattern most teams start from: a timer refetches the product every N seconds, trading freshness against request volume, and still leaving a worst-case gap of N. Or the webhook pattern, where a content change triggers a function that recomputes and purges, and you own every hop. With a live query, the mechanism inverts. The client declares intent once ("render this shape, keep it fresh") and the Content Lake, the queryable store underneath, resolves changes against the query and emits new results.

In practice you keep the initial render server-side for speed and SEO, then attach a live subscription on the client for the fields that actually move: price, availability, badges, countdown state. Static structural content stays cached; volatile fields ride the live stream. That split is the pattern. You are not making the whole page real-time, you are making the parts that matter real-time and leaving the rest fast.

Preview and production on the same pipeline

A recurring source of real-time bugs in commerce is that preview and production are two different systems. Editors preview through one API with one set of caching rules, shoppers hit another, and "it looked right in preview" becomes a genuine ambiguity because preview was never the live path. Every divergence between those two pipelines is a place where a merchandiser approves something that renders differently in the wild.

Sanity collapses that split. The Presentation Tool and Visual Editing render the actual frontend inside Sanity Studio, driven by the same Live Content API that serves production. When a merchandiser edits a price or reorders a collection, they see the live query update in the same preview surface a shopper's page uses, because it is the same query and the same stream. There is no separate preview build to keep in sync, and no class of bug where the preview pipeline lies.

This matters most on drop day, when merchandising decisions are made minutes before or during a launch and there is no time for a staging round trip. An editor can stage a change, watch it resolve live against the real query in the Presentation Tool, and know that what they see is what customers will get. Combined with Content Releases, which lets teams bundle and schedule a set of changes to go live together, you get governed real-time editing: preview parity for confidence, and scheduling for coordination, both riding the same delivery layer rather than a bolted-on preview mode.

Surviving drop-day traffic

Real-time and high-traffic pull in opposite directions if you design them naively. The instinct during a spike is to cache harder, which is exactly when you least want stale prices and stock counts. The pattern that resolves this is layering: serve the structural, slow-changing content from the edge as usual, and reserve the live subscription for the narrow set of fields that must be correct to the second. A product page can be cached as a static shell while its price, inventory badge, and "only 3 left" counter come from a live query. You get edge performance for 95 percent of the bytes and real-time accuracy for the 5 percent that would cost you a sale if it were wrong.

The economics matter here. A short-TTL, purge-everything approach makes traffic spikes and origin load scale together, which is the opposite of what you want when a launch quadruples your concurrent users. Scoping the live layer to volatile fields means the expensive real-time path carries only the data that justifies it, while the cheap cached path absorbs the crowd.

This is also where framing content operations end to end, rather than stopping at publish, earns its keep. Because the same Content Lake serves the live query, the merchandising decision (mark this variant sold out) and the customer-facing consequence (the badge flips, the buy button disables) are one continuous system rather than a publish event followed by a separate, fallible invalidation cascade. During the exact window when your infrastructure is most stressed and your merchandising is most active, that continuity is what keeps the page honest.

Keeping the live path type-safe

A real-time storefront has more moving contracts than a static one. Every live query has a result shape, and every component that renders a live result depends on that shape not drifting. When a schema changes, a field is renamed, a reference is restructured, a variant model gains an option, the danger is that the change ships silently and a live subscription starts returning a shape the frontend did not expect. On a page that updates itself in production, that surfaces as a runtime error in front of shoppers rather than a caught mistake in review.

Sanity's TypeGen addresses this by generating TypeScript types from your schemas and from the GROQ queries themselves. The type is not a generic "document" shape; it is the exact projection your live query asks for, references, slices, filters, and all. When a schema or a query changes in a way that breaks the contract, the mismatch shows up at build time in the components that consume it, not at 12:01 on launch day. For a team shipping merchandising changes quickly against a live delivery layer, that build-time signal is the difference between a caught diff and an incident.

Type safety across the live path also compounds with the editor being real code. Because Sanity Studio is a React application you ship, and its schemas are the same `defineType` definitions TypeGen reads, the model, the editing UI, the query, and the frontend all trace back to one typed source. The live query is not a loosely coupled string against an opaque API; it is a typed contract from schema to subscription to rendered field, which is what lets a small team operate a real-time storefront without a QA army behind every change.

Putting the pattern together

The end-to-end pattern for a real-time storefront on Sanity reads as a sequence of deliberate choices rather than a single switch. Model the catalog so that volatile fields (price, inventory, availability, promotional badges) are addressable in isolation, because that is what lets you scope the live layer tightly later. Write GROQ projections that return exactly the shape each page renders, following references and filtering variants in one round trip so a subscription tracks a single, coherent view. Render the structural shell statically from the edge for speed, then attach a live subscription on the client for the fields that must be correct to the second.

Wire editing through the Presentation Tool so merchandisers preview the same live query production serves, and use Content Releases to schedule coordinated changes for a launch rather than editing live under pressure. Generate types with TypeGen so the live query's shape is a build-time contract, and drift is caught before it reaches a shopper. Each of these is a standard implementation concern in headless commerce; what changes on Sanity is that they share one delivery layer and one queryable store instead of being stitched from a preview SDK, a webhook fan-out, a cache-purge service, and a hand-maintained type map.

That consolidation is the argument. Legacy content systems stop at publishing and leave real-time freshness as an integration you assemble and operate. Treating the query as the live unit, backed by a store that resolves changes against it, moves freshness from something you fight for on every write to something the delivery layer maintains for you. The storefront stays fast because most of it is still cached, and it stays honest because the parts that move are subscribed, not stale.

Real-time content delivery: how the query layer handles live updates

FeatureSanityContentfulStoryblokBuilder.io
Live query subscriptionsLive Content API pushes new query results over SSE; the frontend subscribes to a GROQ query and receives deltas as content changes, no polling loop to hand-roll.Content Preview API plus a Live Preview SDK covers editorial preview; production real-time typically means polling or wiring your own webhook-to-cache invalidation layer.Real-time visual editing via the Bridge in the editor; live production delivery to shoppers generally relies on CDN cache purges triggered by webhooks.Real-time visual updates in the Builder editor and preview; production freshness is handled through their CDN and cache invalidation rather than a live query stream.
Query shape in one round tripGROQ projects exactly the shape the storefront needs, including references followed with `->`, filters, and slices, in a single request that the live layer keeps current.GraphQL and REST; nested references and linked entries often need multiple queries or include-depth params, so a live view can mean several subscriptions to stitch.REST and GraphQL; resolving relations and nested stories usually means `resolve_relations` params or follow-up calls before you can render.Content API returns component and model data; joining across models for a composed page view is done in application code rather than a single query projection.
Stock and price freshness during a dropLive Content API reflects a dataset write to subscribed clients in near real time, so price, badge, and availability fields flip without a full-page cache purge or redeploy.Achievable by pairing webhooks with edge cache invalidation; the round trip from write to purged edge is something you build and operate yourself.Achievable via webhook-driven CDN purges; teams tune cache TTLs to balance freshness against origin load during spikes.Handled through Builder's caching and targeting layer; instantaneous field-level flips across a catalog are a cache-invalidation exercise.
Preview to production parityPresentation Tool plus Visual Editing use the same Live Content API that serves production, so what an editor previews is the live query, not a separate preview pipeline.Live Preview SDK is a distinct path from production delivery, so preview parity is a separate integration to maintain.The Visual Editor Bridge drives preview; production delivery is a different code path with its own caching behavior.Strong in-editor visual preview; production rendering runs through the delivery API and CDN, a separate concern from the editing surface.
Editor customization for merchandisingSanity Studio is a React app you ship; custom input components, Structure Builder, and App SDK let you build merchandising tools next to the content in `sanity.config.ts`.Configurable editor with app framework extensions; core UI is fixed, so bespoke merchandising surfaces live in separate apps rather than the editor itself.Configurable blocks and a visual editor; deep custom editing UI is bounded by the block and plugin model.Visual, drag-and-drop editing optimized for marketers; developer control over the editing UI is framed around registered components.
Type safety across the live layerTypeGen turns schemas and GROQ queries into TypeScript types, so a live subscription's result shape is typed end to end and drift shows up at build time.GraphQL codegen from the schema is available; types track the API schema rather than the exact projection of each live view.TypeScript SDKs exist; end-to-end typing of a specific resolved query shape is largely a manual mapping exercise.SDKs are typed at the client level; per-query result typing across composed models is left to application code.

Ready to try Sanity?

See how Sanity can transform your enterprise content operations.