Next.js SDK
Next.js feature flags that work on both sides
Evaluate a flag in a Server Component, in middleware at the edge, or in a client component, and get the same decision for the same user. No hydration mismatch, no flash of the wrong variant.
01 · Drop it in
The planned Next.js API, exactly as it will ship
The SDK is part of the early-access program, and this is its real surface: one install, one client, one call per decision. Every toggle, rollout step and kill-switch flip you make in the console reaches this code in about 3 seconds, with no redeploy.
Works with the App Router and the Pages Router; flag reads add roughly a millisecond from the local cache.
// app/checkout/page.tsx (Server Component)
import { getFlag } from '@toggled/nextjs/server';
export default async function CheckoutPage() {
const newFlow = await getFlag('checkout.new-flow', {
fallback: false,
user: await currentUser(),
});
return newFlow ? <NewCheckout /> : <ClassicCheckout />;
}
02 · Built for Next.js
What Next.js feature flags get you
Server Components first
getFlag runs during server rendering, so the correct variant is in the HTML you stream. Nothing flickers when the page hydrates.
Middleware and edge ready
Evaluate flags in middleware to rewrite routes for a canary cohort, run an A/B test on a landing page, or gate a whole route group by plan.
One decision on both sides
The server decision is handed to the client SDK during hydration, so a client component reading the same key never disagrees with the server.
03 · Then the usual lifecycle
Flag it, target it, roll it out, measure, kill
Once checkout.new-flow exists in your Next.js code, everything else happens in the console: target the internal team, run a gradual rollout from 1% to 100%, read the impact with built-in A/B testing, and keep the kill switch under your thumb. The full walkthrough is on how Toggled works.
Flat pricing applies here too: unlimited seats and unlimited flags on every plan, so the whole Next.js team gets an account. Numbers are on the pricing page.
Same flags, other stacks
Cohorts agree across SDKs: a user in the 10% on your Next.js side is in the same 10% everywhere else.
Java, Rails, iOS and Android SDKs share the same core and ship with early access.
04 · Where the check goes
Where a flag check belongs in a Next.js codebase
01
Middleware for route-level splits
If the flag decides which route the user lands on, decide it in middleware and rewrite. A canary cohort goes to a different route group, an A/B test splits at the edge, and the pages themselves stay ordinary pages with no flag logic inside them.
02
Server Components for page-level variants
When both variants live on the same route, read the flag once at the top of the Server Component and pass the boolean into the tree. Children take a prop, which keeps them renderable in isolation, and the decision is already in the streamed HTML.
03
Client components only for post-load toggles
Reserve the client hook for things that change after the page is interactive: a panel that opens, a control that appears once the user acts. Anything visible in the first paint should be decided on the server, otherwise you have signed up for a flicker you cannot design around.
05 · Gotchas
Three ways Next.js feature flags go wrong
Gotcha 01
Two evaluations, two different user contexts
The Server Component evaluates with the session user; the client SDK boots with whatever it can see, which is often nothing yet. React then hydrates a different branch than it rendered and logs a mismatch. Bootstrap the client provider with the server decision so the client never re-decides on its own.
Gotcha 02
A flag read that quietly makes the route dynamic
Reading a per-user flag inside a Server Component opts that route out of static rendering, and the page you believed was cached at the edge is now rendered per request. If the flag only touches one widget on an otherwise static page, push the read into a small client island and keep the route cacheable.
Gotcha 03
Middleware that hits the network on every request
Middleware runs for every matching request, and a loose matcher means assets too. If the flag read there is a fetch rather than an in-memory evaluation, you have put a round trip at the front of every page load. Tighten the matcher, and only evaluate with an SDK that works locally in the edge runtime.
06 · Testing
Testing both paths in Next.js
Test the two sides separately, because they fail differently. For a Server Component, call the exported page function with a stubbed flag reader and assert on the markup it returns, or drive a route test with a forced override and check the HTML that comes back. For middleware, build a NextRequest per cohort and assert on the rewrite target instead of the rendered page.
// middleware.test.ts (Vitest)
import { NextRequest } from 'next/server';
import { middleware } from './middleware';
vi.mock('@toggled/nextjs/server', () => ({
getFlag: vi.fn(async () => true),
}));
test('the canary cohort is rewritten to the new checkout', async () => {
const req = new NextRequest('https://app.test/checkout');
const res = await middleware(req);
expect(res.headers.get('x-middleware-rewrite')).toContain('/checkout-v2');
});
07 · People also ask
Next.js feature flag questions, answered
How do you use feature flags in Next.js Server Components?
Call an async flag read inside the component, await getFlag('checkout.new-flow', { user }), and branch before you return JSX. The decision is then baked into the HTML you stream, so nothing changes at hydration. Server Components cannot use hooks, so this has to be a plain async call rather than useFlag.
Why do feature flags cause a hydration mismatch in Next.js?
Because the server and the client evaluated the same key with different inputs. The server had the signed-in user; the client booted anonymous, before the SDK loaded, and React rendered the other branch on rehydrate. Pass the server decision into the client SDK as bootstrap state so both sides start from one value.
Can you evaluate feature flags in Next.js middleware?
Yes, and it is the right place for route-level decisions: rewriting a canary cohort into a different route group, splitting traffic for an A/B test, or blocking a route by plan. Middleware runs at the edge before rendering, so the evaluation has to be local and in memory, never a call to a flag API.
Do feature flags break Next.js caching or static rendering?
They can. A page that reads a per-user flag is dynamic by definition and cannot be one cached artifact for everyone. Keep the read out of statically rendered routes, or evaluate in middleware and vary the rewrite, or scope the branch to a small client component so the rest of the page stays static.
More answers, about the product rather than the code, live on the FAQ.
Early access · launching soon
Put your first Next.js feature behind a flag
Join the early-access list and be first in line when spots open. Flat pricing, unlimited seats, no card required.
No card required · your data stays yours
Keep exploring
More feature flag resources
- Node.js Feature Flags for APIs and Backends
- Python Feature Flags for Django, Flask and FastAPI
- Go Feature Flags With Sub-Millisecond Checks
- Feature Flags Platform
- Managing Feature Flags
- Feature Flag Tools
- A/B Testing Software Powered by Feature Flags
- Feature Flag Service Use Cases for Product Teams
- Feature Flag Software Pricing, Unlimited Seats
- Feature Flags Explained
- LaunchDarkly Alternative With Flat Pricing
- LaunchDarkly Pricing