- Fetch the bundle once on the server.
- Pass it to the client via your framework’s data-loading mechanism.
- Initialize the client SDK with the server-provided bundle as
localConfig. - The client uses the same bundle and resolves identically — no second fetch on hydration.
SvelteKit
Layout load (server)
loadTrafficalBundle respects standard HTTP caching, so subsequent SSR requests within the cache TTL benefit from SvelteKit’s fetch cache.
Root layout (server + client)
On the Svelte SDK the server-fetched bundle goes through
initialBundle (not localConfig). initialBundle is what marks the provider ready during SSR and lets it resolve on the server so the first paint is correct. localConfig is the separate build-time/offline fallback bundle.Page
data.traffical.bundle and renders the correct variant. The client picks up the same bundle and resolves identically. No swap.
Next.js (App Router / RSC)
The React SDK has no@traffical/react/server entry point. Fetch the config bundle directly from the SDK config endpoint — the same URL the client SDK calls — and pass it as localConfig:
fetch integration (next: { revalidate }) caches it, so subsequent renders within the cache window don’t re-fetch.
Next.js (Pages Router)
Why this works
- Same bundle, same hash, same answer. Both server and client read the same bundle and run the same SHA-256 v2 bucketing. The same userId always resolves to the same allocation.
- One network fetch. The server fetches; the client receives the bundle inline. No second fetch on hydration.
- First paint is correct. Because the server resolves before rendering, the user sees the right variant immediately. No flash of original content.
Pitfalls
- Mismatched user IDs. If the server reads
userIdfrom a session cookie but the client reads it from a different source, the two will resolve to different buckets and you’ll see a swap on hydration. Make sure both sides use the same value. - Use the SDK key on both sides. The same
traffical_sk_...SDK key (scopessdk:read+sdk:write) is browser-safe and is used both client-side in theTrafficalProviderand server-side when you fetch the bundle (the plainfetchon Next.js,loadTrafficalBundleon SvelteKit). There is no separate server secret for the SDK path — keep management-scoped keys out of all rendering code. - Stale bundle on long-lived pages. The client refreshes the bundle every 60s by default. SPAs running for hours will pick up new policies automatically. For static pages, a hard reload is enough.
Next steps
SSR + hydration pattern
Full end-to-end example.
React SDK
Provider, hooks, options.
Svelte SDK
Stores, context, runes.