Production Deployment Edge Cases

View as Markdown
Last updated July 17, 2026

Studio works on every common React deploy target. The edges show up around caching (compositions change without code changes, caches need to invalidate), edge-runtime weight limits, and monorepo patterns. This page is the deployment playbook.

ISR + SSG: Cache Invalidation When Compositions Change

Studio compositions are content, not code. Caching them as if they were code means stale layouts persist even after a publish.

The pattern: short revalidation and on-publish webhook

For ISR / on-demand SSG (Next.js, Astro), use a short revalidate AND a Contentstack webhook to invalidate on publish:

// app/blog/[slug]/page.tsx
export const revalidate = 60;   // safety net — 60s max staleness

export default async function BlogPost({ params }) {
  const specOptions = await sdk.fetchCompositionData({ /* … */ });
  return <StudioComponent specOptions={specOptions} />;
}

Then configure a Contentstack webhook on the compositions content type to hit your deploy platform's revalidation API on every publish:

// app/api/revalidate-composition/route.ts
import { revalidatePath, revalidateTag } from "next/cache";

export async function POST(request: Request) {
  const { event, data } = await request.json();
  if (event !== "publish") return Response.json({ ok: true });

  const compositionUid = data.entry.uid;
  const linkedTemplate = data.entry.linked_content_type;   // e.g. "blog_post"
  revalidateTag(`composition:${compositionUid}`);
  revalidatePath(`/${linkedTemplate}/[slug]`);
  return Response.json({ revalidated: true });
}

This combination gives you fast cache misses on publish (the webhook) AND a backstop in case the webhook fires late or misses (the 60s revalidate).

What not to do

Don'tWhy
revalidate = false (cache forever) without a webhookA composition publish doesn't invalidate the cache; layout changes never appear
revalidate = 0 (always fresh) on every visitor routeDefeats ISR; every visitor pays a full SSR render
Tag-based caching without tagging the composition UIDrevalidateTag can't target specific routes when compositions change

CDN Cache Invalidation

If you're behind a CDN (Cloudflare, Fastly, CloudFront), the deploy-platform revalidation isn't enough, the CDN's edge cache must also flush.

The pattern: webhook hits your origin's revalidate endpoint AND purges the CDN. Most platforms have an API for surgical purge by URL or tag:

async function purgeCDN(paths: string[]) {
  await fetch("https://api.cloudflare.com/client/v4/zones/<zone>/purge_cache", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.CF_API_TOKEN}` },
    body: JSON.stringify({ files: paths.map(p => `https://yoursite.com${p}`) }),
  });
}

Trigger this from the same webhook handler as the deploy-platform revalidation.

Edge Runtime Compatibility

Studio's SDK currently exceeds the Vercel Edge / Cloudflare Workers 1 MB limit for many configurations. For edge-deployed routes:

  • Use Node runtime for Studio routes. Mark the route file: ts export const runtime = "nodejs"; // Next.js App Router
  • Keep edge-deployed routes minimal (auth checks, redirects, simple JSON APIs) and proxy Studio renders to Node-deployed routes.
  • For full edge SSR: wait for the SDK's edge-runtime story to mature OR ship hand-coded routes for the edge-critical pages.

The SDK team is actively shrinking the edge-runtime footprint; this constraint relaxes over time.

Monorepo Patterns

For monorepos where Studio is one of several apps:

Shared component library

Components live in a shared package; both the Studio-rendered app and other apps consume them. The Studio-rendered app's register-components.tsx imports from the shared package, no duplication.

Click to enlarge

Shared Contentstack config

The lib/contentstack.ts factory lives in a shared package; both apps init the SDK with their own credentials.

Independent deploys

Each app deploys independently. Studio renders don't block deploys of other apps. Composition publishes flow through Contentstack webhooks to the Studio-rendered app's revalidate endpoint only.

Deploy-Platform Specifics

PlatformStudio runtimeCachingNotes
VercelNode only (edge limit)ISR + on-demand revalidate + revalidateTagUse runtime = "nodejs" for Studio routes
NetlifyNodeOn-demand builders + cache tagsSame pattern; netlify-functions for the revalidate handler
Cloudflare PagesWorkers (size constrained)Cache rules + purge APIUse Pages Functions + Node runtime for Studio routes
AWS AmplifyLambda (no edge limit)CloudFront invalidation via webhookTrickier: CloudFront invalidation is path-based, plan paths up front
Self-hosted (Node)NodeWhatever you buildSame patterns; just wire the webhook to cache invalidation yourself

Patterns to Avoid

PatternWhy it bites
Caching SSR output without including the variant + locale in the cache keyStale variant/locale content served to wrong visitors
Ignoring the publish webhook, all caches go stale until the safety-net revalidate firesAuthors publish; nothing changes for visitors for minutes
Deploying Studio routes to edge runtime without confirming size limitsBuild fails or the route OOMs at request time
Running the same Studio project against staging + production environmentsOne author edit in staging accidentally affects production
Monorepo + duplicated component registrations across appsTwo apps register the same type UID differently; Studio uses whichever loaded last

What's Still Unsolved

  • Edge-runtime SSR for Studio: a major open item. Until the SDK shrinks, Node-only is the answer.
  • CDN tag-based purge across multiple compositions: most CDNs purge by URL or by surrogate-key; if you have hundreds of routes and one section's composition changes affecting all of them, surgical purge is non-trivial. Workaround: shorter revalidate for affected routes.
  • Multi-region deploys with composition replication: Contentstack's CDA handles read-replicas across regions, but composition publishes propagate at content-stack speed (seconds). For sub-second cross-region consistency, you're back to short revalidate.

See Also