Safe deployments, gradual rollouts, and risk-free releases
You ship code to production. It breaks. Now you're scrambling to rollback.
What if you could deploy code but control when it goes live?
Deploy: Push code to production servers
Release: Make features visible to users
Feature flags decouple these two actions.
You can deploy on Monday. Release on Friday. Rollback instantly without redeploying.
Runtime configuration switches that enable or disable functionality without deploying new code.
function processPayment(order: Order) {
if (featureFlags.isEnabled('new-payment-gateway')) {
return newPaymentGateway.process(order)
}
return legacyPaymentGateway.process(order)
}
One deployment. Two code paths. You choose which runs.
Release Toggles: Gradual rollouts of new features (short-lived, weeks)
Experiment Toggles: A/B tests and multivariate testing (duration of test)
Ops Toggles: Kill switches during outages (permanent circuit breakers)
Permission Toggles: Premium features, access control (permanent)
// Flag evaluation service
class FeatureFlagService {
private flags: Map<string, boolean>
async isEnabled(flagName: string, userId?: string): boolean {
const config = await this.getConfig(flagName)
return this.evaluate(config, userId)
}
private evaluate(config: FlagConfig, userId?: string): boolean {
// Percentage rollout
if (config.percentage < 100) {
return this.hash(userId) < config.percentage
}
return config.enabled
}
}
Start small. Monitor. Expand.
Day 1: 1% of users (internal team) Day 2: 5% of users (early adopters) Day 4: 25% of users (canary release) Day 7: 50% of users (half production) Day 10: 100% of users (full release)
Problem at any stage? Flip the flag to 0% instantly.
Named after canaries in coal mines—they detect danger early.
// Route 5% to new service, 95% to legacy
const flagConfig = {
name: 'new-checkout-flow',
percentage: 5,
enabled: true,
monitoringMetrics: ['error_rate', 'latency', 'conversion']
}
If error rate spikes with the 5%, kill the flag before it hits everyone.
Not just percentages. Target specific user groups.
const flagRules = {
name: 'ai-recommendations',
rules: [
{ segment: 'internal', enabled: true },
{ segment: 'premium-users', enabled: true },
{ segment: 'beta-testers', enabled: true },
{ segment: 'region:us-west', percentage: 25 },
{ default: false }
]
}
Roll out by: team, tier, region, device, behavior.
// Legacy modernization with feature flags
export class OrderProcessor {
async processOrder(order: Order) {
const useNewService = await flags.isEnabled(
'modern-order-service',
order.customerId
)
if (useNewService) {
return this.modernService.process(order)
}
// Fallback to legacy
return this.legacyService.process(order)
}
}
// Gradual migration with monitoring
export class PaymentRouter {
async routePayment(payment: Payment) {
const config = await flags.getConfig('new-payment-api')
// Check eligibility first
if (!this.isEligible(payment, config)) {
return this.legacy.process(payment)
}
try {
const result = await this.modern.process(payment)
this.metrics.recordSuccess('modern')
return result
} catch (error) {
this.metrics.recordFailure('modern', error)
// Auto-fallback to legacy
return this.legacy.process(payment)
}
}
}
Etsy deploys 50+ times per day using feature flags.
Their approach:
Result: Confidence to ship continuously without fear.
Flags left in code become technical debt.
Lifecycle stages:
Set expiration dates when you create flags. 30-90 days max for release toggles.
DO:
DON'T:
Use feature flags when:
Don't use flags for:
Strangler Fig: Route traffic between old and new systems
if (flags.isEnabled('new-customer-api')) {
return newSystem.getCustomer(id)
}
return legacySystem.getCustomer(id)
Branch by Abstraction: Switch implementations behind abstraction
const implementation = flags.isEnabled('new-db')
? newDatabase : legacyDatabase
Parallel Run: Control traffic split for dual writes
if (flags.percentage('dual-write') > random()) {
await Promise.all([old.write(), new.write()])
}
Decouple deployment from release – ship code safely, release confidently
Gradual rollouts reduce risk – 1% → 5% → 25% → 50% → 100%
Flags are temporary – clean up or they become tech debt
Feature flags turn deployment from a scary event into a non-event.
Week 1: Foundation
Week 2: First flags
Week 3: Process
Start small. Build confidence. Scale gradually.