Kill-Switch a Feature

Goal: Disable a broken feature instantly for all users — no deploy, no rollback, no incident escalation at 3am.

The idea

Every feature flag is implicitly a kill-switch. If you wrapped a feature in a flag, you can disable it in seconds from the dashboard.

The change takes effect on the next API call — typically within milliseconds for your users.

Setting up a flag as a kill switch

  1. 1
    Create a flag for the risky feature

    Go to Flags and create a new flag. Name it after the feature, for example Payment Processor v2 with key payment-processor-v2.

  2. 2
    Add a STATIC rule that serves true

    On the flag's detail page, open the Rules tab for your Production environment.

    Click Add Rule → select Static.

    Set Serve value to true and Priority to 0. Click Save.

    This means: when the flag is enabled, everyone gets true.

  3. 3
    Enable the flag

    Toggle the Production environment switch to Enabled.

    Your application now receives value: true for this flag.

    {
      "value": true,
      "matchedRuleType": "STATIC",
      "error": null
    }
  4. 4
    When something goes wrong — toggle it off

    In the dashboard, find the flag and toggle the Production environment switch to Disabled.

    The next evaluation returns value: false for every user, immediately:

    {
      "value": false,
      "matchedRuleType": null,
      "error": {
        "type": "FLAG_DISABLED",
        "message": "Flag disabled"
      }
    }
  5. 5
    Toggle back on when the issue is resolved

    Once you've deployed the fix, re-enable the flag from the same toggle. Evaluations return value: true again on the next request.

The toggle is instant. The very next API call after toggling reflects the new state. There is no propagation delay or cache to flush.

Handling FLAG_DISABLED in your code

Your application should treat value: false as the safe fallback regardless of what error.type is set to. Never gate your feature path on the absence of an error — always use value:

const result = await evaluateFlag("payment-processor-v2", userId);

if (result.value === true) {
  return runPaymentProcessorV2();
}

// value is false — flag disabled, no matching rule, or not found
return runLegacyPaymentProcessor();

Never check error.type to gate your feature. Always use value. The error field is for observability and alerting, not branching logic.

Re-enabling after a fix

Once you've deployed the fix, re-enable the flag from the same toggle. You don't need to rebuild or redeploy anything.

Every toggle is recorded in Audit Logs (Team plan and above) — who disabled it, at what time. Useful for post-mortems.

Best practices

Wrap risky code paths before you ship. The kill-switch only helps if it was there from the beginning. Any significant feature that touches payment flows, data writes, or user-facing UI should have a flag wrapping it before going to production.

Test the disabled path. Before enabling a flag in production, verify that your false code path renders correctly. A broken fallback is almost as bad as a broken feature.

Name flags by feature, not by toggle intent. new-checkout is better than enable-new-checkout or checkout-kill-switch. The flag name describes the feature; whether it's on or off is just its current state.

Was this helpful?