Skip to main content

Feature Flags and Experiments with PostHog in Next.js

How to ship safer by wrapping new features in flags, measuring impact, and rolling back fast.

JDJohn Doe

Ship Fast, Hide Risk

Feature flags let you merge early, release selectively, and back out without redeploying. This guide uses PostHog + Next.js to keep changes small, observable, and reversible.

Flags are not just toggles—they are contracts for rollback.

The Minimal Flag Hook

import posthog from "posthog-js";
 
export function useFlag(flag: string, fallback = false) {
  const [enabled, setEnabled] = useState(fallback);
 
  useEffect(() => {
    const ph = posthog;
    if (!ph) return setEnabled(fallback);
    setEnabled(ph.isFeatureEnabled(flag));
    const off = ph.onFeatureFlags(() => setEnabled(ph.isFeatureEnabled(flag)));
    return () => off();
  }, [flag, fallback]);
 
  return enabled;
}

Rollout Steps (Do Them in Order)

  1. Create the flag in PostHog (description + owner + expiry date).
  2. Ship the code behind useFlag("new-onboarding") with a safe fallback.
  3. Enable for internal team only; validate metrics are flowing.
  4. Gradually ramp to 10% → 25% → 50% while watching error logs and conversion.
  5. Decide: graduate, iterate, or kill. Archive flags you keep off.

Flags without owners or expiry dates become debt. Add both when you create the flag to force cleanup.

Instrument the Experiment

export function OnboardingButton() {
  const useNewFlow = useFlag("new-onboarding", false);
 
  const handleClick = () => {
    posthog.capture("onboarding_clicked", { variant: useNewFlow ? "new" : "old" });
    // route users to the right experience
  };
 
  return (
    <Button onClick={handleClick}>
      {useNewFlow ? "Start the faster flow" : "Start onboarding"}
    </Button>
  );
}

Metrics to Watch

StageMetricExpected Direction
ExposureFlag exposure eventsFlat → increasing
ConversionOnboarding completion rateUp
StabilityError rate (Sentry/Logs)Flat/Down
RetentionD1/D7 activationUp

When to Kill a Flag

  • The flag is off for 14 days and has no owner.
  • The new variant is strictly worse on the primary metric.
  • The code path complicates debugging or doubles test cases.

Removing flags is a feature, not cleanup—every deleted flag makes the next launch calmer.