Implement a feature flag system in middleware by reading cookies for persistent assignments, using deterministic logic to assign variants, and using NextResponse.rewrite to serve different page versions without changing the visible URL
Implementing a feature flag system using Next.js middleware allows you to route users to different page variants at the edge, before the page even renders. This approach gives you the power to run A/B tests, roll out features progressively, or show experimental UI to specific user segments—all without rebuilding your application. The core pattern involves: reading or assigning a variant in middleware, storing that decision in a cookie for consistency, and using NextResponse.rewrite() to serve the appropriate page variant while keeping the original URL in the browser address bar .
For more sophisticated needs, the Vercel Flags SDK provides a production-ready foundation. It handles flag definitions, type safety, and integrates with popular providers like LaunchDarkly, Optimizely, and Statsig [citation:9]. The SDK's precompute pattern is particularly powerful for static generation with feature flags—it pre-renders multiple versions of your pages with different flag values, then middleware serves the appropriate version based on the user's assignment [citation:6].
For experiments that involve completely different page structures, you can combine middleware rewrites with separate page files. The Soda SDK [citation:8] demonstrates this pattern elegantly: you define experiments with variant routes, and the SDK automatically assigns users and rewrites to the appropriate path. The user sees /mattress in their browser, but the server serves content from /mattress-a or /mattress-b. This keeps your experiment implementation clean and maintainable.
A critical requirement for feature flags is consistency—users shouldn't flip between variants on each visit. The standard solution is to store assignments in cookies [citation:2]. In the middleware, always check for an existing cookie before assigning a variant. This ensures users have a stable experience and your experiment data remains clean. The cookie should be HttpOnly for security and set with a reasonable expiration (e.g., 30-90 days) to cover the experiment duration [citation:8].
No feature flag system is complete without analytics. When middleware assigns a variant, you should log that decision to your analytics platform. This can be done by setting a cookie that client-side analytics can read, or by calling an analytics API route from the middleware (being careful not to slow down the response) [citation:7]. PostHog, Amplitude, and Segment all provide ways to track experiment assignments and measure conversion differences between variants.
Performance: Middleware must be fast—avoid blocking operations like network requests to external flag services unless absolutely necessary [citation:8].
Cache invalidation: If using a remote flag service, implement caching with appropriate TTL to balance freshness and performance [citation:8].
Fallback behavior: Always have a default variant in case your flag service is unavailable or middleware errors occur [citation:8].
Bot exclusion: Consider excluding known bots from experiments to avoid skewing your data. Check user-agent headers in middleware.
Preview capabilities: Build a way for internal users to force specific variants for testing (e.g., query parameters or admin cookies).