Ideas Engineered for Tomorrow
We Engineer Services & Solutions for Your Business Needs
Home About
Products
Services
Hire
Industries
Consulting
Partners
Articles Careers Contact
Software Development

Feature Flags: Ship Code Without Shipping Risk

Feature flags let you deploy code to production without exposing it to users — then roll it out gradually, test with real traffic, and kill it instantly if something breaks.

November 18, 2025 11 min read

We shipped a checkout redesign to 100% of users on a Friday afternoon. Conversion dropped 12% over the weekend. By Monday morning, we'd lost ₹3.2 lakh in revenue. If we'd had a feature flag, we could have rolled back in 10 seconds instead of waiting for a hotfix deployment. That's the day we adopted feature flags for every significant change.

Types of Feature Flags

Not all flags are the same. Using the wrong type for your use case leads to flag sprawl and technical debt.

Type Purpose Lifetime Example
Release flag Control when a feature becomes visible Days to weeks "New checkout flow" — roll out to 10%, then 50%, then 100%
Experiment flag A/B testing, measuring impact Weeks to months "Green vs blue CTA button" — 50/50 split, measure conversion
Ops flag (kill switch) Disable features during incidents Permanent "Disable recommendations" — turn off when recommendation service is down
Permission flag Gate features for specific users/plans Permanent "Advanced analytics" — only for Enterprise plan customers

Release flags should be temporary — once the feature is fully rolled out, remove the flag. Ops and permission flags are permanent parts of your system. This distinction matters for lifecycle management.

Implementation Patterns

Basic Implementation

// Simple feature flag service
interface FeatureFlags {
  isEnabled(flagName: string, context?: UserContext): boolean;
}

// Usage in application code
function renderCheckout(user: User) {
  if (featureFlags.isEnabled('new-checkout-flow', { userId: user.id })) {
    return renderNewCheckout(user);
  }
  return renderOldCheckout(user);
}

// Usage in API route
app.post('/api/orders', async (req, res) => {
  if (featureFlags.isEnabled('batch-order-processing')) {
    return batchOrderHandler(req, res);
  }
  return singleOrderHandler(req, res);
});

Flag Evaluation Rules

Flags evaluate to true or false based on rules. Common targeting rules:

  • Percentage rollout: 10% of all users see the new feature (consistent per user via hash)
  • User targeting: Specific users or groups (internal team, beta testers, enterprise customers)
  • Attribute targeting: Users in India, users on mobile, users who signed up after a certain date
  • Environment: Enabled in staging, disabled in production

Consistent Hashing for Percentage Rollouts

When you set a flag to 10%, the same user should always see the same variant. Don't use Math.random() — use a hash of the user ID:

function isInPercentage(userId: string, flagName: string, percentage: number): boolean {
  // Hash user ID + flag name for consistent assignment
  const hash = murmurhash3(`${flagName}:${userId}`);
  const bucket = hash % 100;
  return bucket < percentage;
}

// User "usr_abc" gets bucket 37 for "new-checkout"
// At 10%: excluded (37 >= 10)
// At 50%: included (37 < 50)
// At 100%: included
// The user's assignment only changes when you change the percentage

Gradual Rollout Strategies

The Safe Rollout Plan

  1. 0% → Internal team (dogfooding) — Enable for employees only. Use for 2-3 days. Catch obvious issues
  2. 1% → Canary — Real users, minimal blast radius. Monitor error rates, latency, conversion. Run for 24 hours
  3. 10% → Early rollout — Statistically significant sample. Compare metrics between flag-on and flag-off cohorts. Run for 2-3 days
  4. 50% → Broad rollout — If metrics are good at 10%, expand. This is also where you can run A/B tests for conversion impact
  5. 100% → Full rollout — All users. Monitor for 1 week
  6. Remove flag — After 1 week at 100% with no issues, delete the flag and the old code path
The rollback plan is always: set the flag to 0%. This is why feature flags are powerful — rollback is a config change, not a deployment. It takes 10 seconds, not 10 minutes.

Tools Comparison

Tool Best For Pricing Our Take
LaunchDarkly Enterprise, complex targeting, experimentation From $10/seat/month Category leader. Best UI and SDK support. Worth the cost for 20+ flags
Unleash Self-hosted, open source Free (OSS) or hosted from $80/month Best open-source option. Self-host for data sovereignty. UI is decent
ConfigCat Simple flags, small teams Free (10 flags) → $39/month Simplest to set up. Good for startups. Limited targeting
Flagsmith Feature flags + remote config Free (OSS) or hosted from $45/month Good alternative to Unleash with better UI. Combines flags with config management
DIY (database/config) 1-5 simple on/off flags Free Fine for simple toggles. Don't build a flagging system from scratch — buy or use OSS

Flag Lifecycle Management

Technical debt from abandoned flags is the #1 complaint we hear. A codebase with 200 stale flags is harder to maintain than one without flags.

Rules We Follow

  • Every release flag gets an expiry date. Set it when creating the flag. 30 days after full rollout, the flag must be removed
  • Flag cleanup is part of the definition of done. A feature isn't "done" until the flag is removed and the old code path is deleted
  • Monthly flag audit. Review all flags older than 30 days. Is it fully rolled out? Remove it. Is it at 50% for 3 months? Make a decision and move on
  • Name flags with intent. release-new-checkout-q4-2025 is better than flag-123. When someone sees it in 6 months, they should know what it's for

Common Pitfalls

Pitfall What Happens Prevention
Flag combinatorics Flag A × Flag B × Flag C = 8 possible states. Testing all combinations is exponential Keep flags independent. If two flags interact, make one depend on the other explicitly
Stale flags 200 flags, nobody knows which are active. New devs afraid to remove any Expiry dates, monthly audits, ownership per flag
Testing gaps Tests only run with flags on. The flag-off path silently breaks CI runs tests with all flag combinations for critical paths. Or at minimum, both on and off
Performance Flag evaluation on every request adds latency if flags are fetched remotely Cache flag values locally with TTL. Most flag SDKs do this automatically

Frequently Asked Questions

When should we use feature flags vs feature branches?

Feature flags for changes that affect existing functionality or need gradual rollout. Feature branches for isolated new code. The best teams use both: develop on a short-lived branch, merge to main behind a feature flag, then roll out gradually. This gives you both code isolation and deployment control.

How many feature flags is too many?

There's no magic number, but if you have more than 50 active release flags, something is wrong — flags aren't being cleaned up. Permanent flags (ops, permissions) don't count toward this limit. We target under 20 active release flags at any time for a typical team of 10-15 developers.

Can feature flags replace staging environments?

Not entirely, but they reduce staging's importance. With flags, you can test in production with real data (for internal users first). Staging is still useful for integration testing and catching obvious issues before any real user exposure. Think of flags as complementing staging, not replacing it.

Pillai Infotech Engineering Team

Feature flags are part of our standard deployment process. Every significant change ships behind a flag first — we've avoided countless incidents because a flag flip is faster than any rollback.

Need Help With Safe Deployment Practices?

From feature flags to canary deployments — we help teams ship confidently with zero-downtime releases.

Get a Free Consultation Our Services