xiaohongshu
xiaohongshu
Using runtime switches to enable or disable features without deploying new code, decoupling deployment from release and enabling gradual rollouts, A/B testing, and emergency feature disabling.
Full skill instructions
Current Level: Intermediate
Domain: DevOps / Feature Management
Feature toggles are runtime switches that enable or disable features without deploying new code. They decouple deployment from release, enabling gradual rollouts, A/B testing, and emergency feature disabling without code changes.
┌─────────────────────────────────────────────────────────────────┐
│ Feature Toggle Concept │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Code Deployed ──▶ Feature Toggle OFF ──▶ Feature Hidden │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Code Deployed ──▶ Feature Toggle ON ──▶ Feature Visible│ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
| Benefit | Impact |
|---|---|
| Trunk-Based Development | No long-lived branches |
| Dark Launches | Deploy without activating |
| Gradual Rollout | Enable for 5%, 50%, 100% |
| Kill Switch | Disable if issues |
| A/B Testing | Test variants |
// Release toggle (temporary)
function showNewCheckout() {
if (featureEnabled('new-checkout')) {
return <NewCheckout />;
} else {
return <OldCheckout />;
}
}
// Usage
const checkout = showNewCheckout();
// Experiment toggle (A/B testing)
function showCheckoutVariant() {
const variant = getExperimentVariant('checkout-test');
if (variant === 'A') {
return <CheckoutVariantA />;
} else {
return <CheckoutVariantB />;
}
}
// Usage
const checkout = showCheckoutVariant();
// Ops toggle (circuit breaker)
function makePayment() {
if (featureEnabled('payments-enabled')) {
return processPayment();
} else {
return showMaintenanceMessage();
}
}
// Usage
const payment = makePayment();
// Permission toggle (user-based)
function showPremiumFeature() {
if (userHasPermission('premium')) {
return <PremiumFeature />;
} else {
return <UpgradePrompt />;
}
}
// Usage
const feature = showPremiumFeature();
// Simple boolean flag
const featureFlags = {
newCheckout: false,
premiumFeature: true,
paymentsEnabled: true
};
function featureEnabled(flag) {
return featureFlags[flag] || false;
}
// Usage
if (featureEnabled('newCheckout')) {
showNewCheckout();
}
// config/feature-flags.json
{
"newCheckout": false,
"premiumFeature": true,
"paymentsEnabled": true
}
// Load config file
const fs = require('fs');
const featureFlags = JSON.parse(fs.readFileSync('config/feature-flags.json'));
function featureEnabled(flag) {
return featureFlags[flag] || false;
}
// Usage
if (featureEnabled('newCheckout')) {
showNewCheckout();
}
-- Feature flags table
CREATE TABLE feature_flags (
id SERIAL PRIMARY KEY,
flag_name VARCHAR(255) NOT NULL UNIQUE,
flag_value BOOLEAN NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Insert feature flags
INSERT INTO feature_flags (flag_name, flag_value)
VALUES ('newCheckout', false),
('premiumFeature', true),
('paymentsEnabled', true);
// Load from database
async function loadFeatureFlags() {
const result = await db.query('SELECT flag_name, flag_value FROM feature_flags');
const featureFlags = {};
result.rows.forEach(row => {
featureFlags[row.flag_name] = row.flag_value;
});
return featureFlags;
}
async function featureEnabled(flag) {
const featureFlags = await loadFeatureFlags();
return featureFlags[flag] || false;
}
// Usage
if (await featureEnabled('newCheckout')) {
showNewCheckout();
}
// LaunchDarkly
const LaunchDarkly = require('ldclient-node');
const client = LaunchDarkly.init('sdk-key');
client.on('ready', () => {
const flagValue = client.variation('new-checkout', false, {
key: 'user-123'
});
if (flagValue) {
showNewCheckout();
} else {
showOldCheckout();
}
});
// Boolean toggle (on/off)
const flagValue = client.variation('new-checkout', false, user);
// Percentage rollout (20% of users)
const flagValue = client.variation('new-checkout', false, user, {
percentage: 20
});
// User targeting (specific user IDs)
const flagValue = client.variation('new-checkout', false, user, {
users: ['user-123', 'user-456']
});
// Segment targeting (beta users, paid users)
const flagValue = client.variation('new-checkout', false, user, {
segments: ['beta', 'paid']
});
// Environment-based (on in prod, off in staging)
const flagValue = client.variation('new-checkout', false, user, {
environments: {
production: true,
staging: false
}
});
// Server-side evaluation
app.get('/checkout', (req, res) => {
const flagValue = client.variation('new-checkout', false, req.user);
if (flagValue) {
res.send('<NewCheckout />');
} else {
res.send('<OldCheckout />');
}
});
// Client-side evaluation
const flagValue = client.variation('new-checkout', false, user);
if (flagValue) {
render(<NewCheckout />);
} else {
render(<OldCheckout />);
}
// Hybrid evaluation (some server, some client)
app.get('/checkout', (req, res) => {
const serverFlag = client.variation('payments-enabled', false, req.user);
if (serverFlag) {
res.send({
checkout: 'new',
payments: true
});
} else {
res.send({
checkout: 'old',
payments: false
});
}
});
// Dark launch (code deployed but off)
function darkLaunch() {
// Deploy code
deployNewVersion();
// Feature is off by default
setFeatureFlag('new-checkout', false);
// No users see new feature
console.log('Dark launch: feature is off');
}
darkLaunch();
// Enable for internal users (dogfooding)
function enableForInternalUsers() {
// Enable for internal users
setFeatureFlag('new-checkout', true, {
users: ['[email protected]', '[email protected]']
});
console.log('Enabled for internal users');
}
enableForInternalUsers();
// Ramp to 5% of users
function rampTo5Percent() {
setFeatureFlag('new-checkout', true, {
percentage: 5
});
console.log('Ramped to 5%');
}
rampTo5Percent();
// Ramp to 50% of users
function rampTo50Percent() {
setFeatureFlag('new-checkout', true, {
percentage: 50
});
console.log('Ramped to 50%');
}
rampTo50Percent();
// Ramp to 100% of users
function rampTo100Percent() {
setFeatureFlag('new-checkout', true, {
percentage: 100
});
console.log('Ramped to 100%');
}
rampTo100Percent();
// Remove toggle after full rollout
function removeToggle() {
// Remove feature flag code
// Always show new feature
// Clean up old code
console.log('Toggle removed');
}
removeToggle();
// Variant A (50% of users)
const variantA = client.variation('checkout-test', 'A', user);
if (variantA === 'A') {
render(<CheckoutVariantA />);
}
// Variant B (50% of users)
const variantB = client.variation('checkout-test', 'B', user);
if (variantB === 'B') {
render(<CheckoutVariantB />);
}
// Track metrics for each variant
function trackCheckoutEvent(variant, event) {
analytics.track({
event: event,
variant: variant,
user: user.id
});
}
// Usage
const variant = client.variation('checkout-test', 'A', user);
renderCheckout(variant);
trackCheckoutEvent(variant, 'checkout_viewed');
// Determine winner based on metrics
function determineWinner() {
const metrics = analytics.getMetrics('checkout-test');
const conversionA = metrics.A.conversionRate;
const conversionB = metrics.B.conversionRate;
if (conversionA > conversionB) {
return 'A';
} else {
return 'B';
}
}
// Usage
const winner = determineWinner();
setFeatureFlag('checkout-test', winner);
// Kill switch: disable feature if issues
function killSwitch() {
setFeatureFlag('payments-enabled', false);
console.log('Payments disabled');
}
killSwitch();
// No redeployment needed
function disableFeatureWithoutRedeploy() {
// Disable feature
setFeatureFlag('new-checkout', false);
// No code changes needed
// No redeployment needed
console.log('Feature disabled');
}
disableFeatureWithoutRedeploy();
// Create toggle for new feature
function createToggle() {
setFeatureFlag('new-checkout', false);
console.log('Toggle created');
}
createToggle();
// Use toggle during development
function useDuringDevelopment() {
// Toggle is off by default
setFeatureFlag('new-checkout', false);
// Developers can enable locally
if (process.env.NODE_ENV === 'development') {
setFeatureFlag('new-checkout', true);
}
}
useDuringDevelopment();
// Enable gradually
function enableGradually() {
// Enable for 5% of users
setFeatureFlag('new-checkout', true, { percentage: 5 });
// Wait and monitor
setTimeout(() => {
// Enable for 25% of users
setFeatureFlag('new-checkout', true, { percentage: 25 });
// Wait and monitor
setTimeout(() => {
// Enable for 50% of users
setFeatureFlag('new-checkout', true, { percentage: 50 });
// Wait and monitor
setTimeout(() => {
// Enable for 100% of users
setFeatureFlag('new-checkout', true, { percentage: 100 });
}, 3600000); // 1 hour
}, 3600000); // 1 hour
}, 3600000); // 1 hour
}
enableGradually();
// Feature fully released
function featureFullyReleased() {
// All users see new feature
setFeatureFlag('new-checkout', true, { percentage: 100 });
console.log('Feature fully released');
}
featureFullyReleased();
// Remove toggle after full rollout
function removeToggle() {
// Remove feature flag code
// Always show new feature
// Clean up old code
console.log('Toggle removed');
}
removeToggle();
// Old toggles = complexity
function oldToggles() {
// Many old toggles in code
if (featureEnabled('old-feature-1')) { /* ... */ }
if (featureEnabled('old-feature-2')) { /* ... */ }
if (featureEnabled('old-feature-3')) { /* ... */ }
// ... many more
}
oldToggles();
// Regular cleanup: remove old toggles
function cleanupOldToggles() {
// Remove old feature flag code
// Clean up old code
console.log('Old toggles removed');
}
cleanupOldToggles();
// Set expiration dates on toggles
function setExpirationDate() {
setFeatureFlag('new-checkout', true, {
expirationDate: '2024-12-31'
});
console.log('Expiration date set');
}
setExpirationDate();
// LaunchDarkly
const LaunchDarkly = require('ldclient-node');
const client = LaunchDarkly.init('sdk-key');
client.on('ready', () => {
const flagValue = client.variation('new-checkout', false, {
key: 'user-123'
});
if (flagValue) {
showNewCheckout();
} else {
showOldCheckout();
}
});
// Split.io
const SplitFactory = require('@splitsoftware/splitio').SplitFactory;
const factory = SplitFactory({
core: {
authorizationKey: 'sdk-key'
}
});
const client = factory.client();
client.on(client.Event.SDK_READY, () => {
const treatment = client.getTreatment('new-checkout', 'user-123');
if (treatment === 'on') {
showNewCheckout();
} else {
showOldCheckout();
}
});
// Unleash
const unleash = require('unleash-client');
unleash.initialize({
url: 'https://unleash.example.com/api',
appName: 'my-app',
instanceId: 'my-instance-id'
});
unleash.on('ready', () => {
if (unleash.isEnabled('new-checkout')) {
showNewCheckout();
} else {
showOldCheckout();
}
});
// Flagsmith
const Flagsmith = require('flagsmith-nodejs-sdk');
const flagsmith = new Flagsmith({
environmentKey: 'env-key'
});
flagsmith.getEnvironmentFlags().then(flags => {
const newCheckout = flags.isFeatureEnabled('new-checkout');
if (newCheckout) {
showNewCheckout();
} else {
showOldCheckout();
}
});
// ConfigCat
const ConfigCatClient = require('configcat-node');
const client = ConfigCatClient.get('sdk-key');
client.getValueAsync('new-checkout', false, user).then(value => {
if (value) {
showNewCheckout();
} else {
showOldCheckout();
}
});
// Config file (simple, requires redeploy)
const fs = require('fs');
function loadFeatureFlags() {
const config = JSON.parse(fs.readFileSync('config/feature-flags.json'));
return config;
}
function featureEnabled(flag) {
const flags = loadFeatureFlags();
return flags[flag] || false;
}
// Usage
if (featureEnabled('new-checkout')) {
showNewCheckout();
}
// Database table (dynamic, adds latency)
async function loadFeatureFlags() {
const result = await db.query('SELECT flag_name, flag_value FROM feature_flags');
const flags = {};
result.rows.forEach(row => {
flags[row.flag_name] = row.flag_value;
});
return flags;
}
async function featureEnabled(flag) {
const flags = await loadFeatureFlags();
return flags[flag] || false;
}
// Usage
if (await featureEnabled('new-checkout')) {
showNewCheckout();
}
// Redis (fast, requires Redis)
const redis = require('redis');
const client = redis.createClient();
async function loadFeatureFlags() {
const flags = await client.hgetall('feature-flags');
return flags;
}
async function featureEnabled(flag) {
const flags = await loadFeatureFlags();
return flags[flag] === 'true';
}
// Usage
if (await featureEnabled('new-checkout')) {
showNewCheckout();
}
// Cache flag values (don't query every request)
const flagCache = new Map();
async function featureEnabled(flag) {
// Check cache first
if (flagCache.has(flag)) {
return flagCache.get(flag);
}
// Load from source
const value = await loadFlagValue(flag);
// Cache the value
flagCache.set(flag, value);
// Invalidate cache after 5 minutes
setTimeout(() => {
flagCache.delete(flag);
}, 300000);
return value;
}
// Usage
if (await featureEnabled('new-checkout')) {
showNewCheckout();
}
// Evaluate flags once per request
app.use((req, res, next) => {
req.flags = {};
next();
});
app.get('/checkout', (req, res) => {
// Evaluate flag once
if (!req.flags.newCheckout) {
req.flags.newCheckout = client.variation('new-checkout', false, req.user);
}
if (req.flags.newCheckout) {
res.send('<NewCheckout />');
} else {
res.send('<OldCheckout />');
}
});
// Minimal overhead: use in-memory cache
const flagCache = new Map();
function featureEnabled(flag) {
// In-memory cache (fastest)
return flagCache.get(flag) || false;
}
// Load flags on startup
async function loadFlags() {
const flags = await loadFeatureFlags();
Object.entries(flags).forEach(([key, value]) => {
flagCache.set(key, value);
});
}
loadFlags();
// Usage
if (featureEnabled('new-checkout')) {
showNewCheckout();
}
// Test both paths (on and off)
describe('New Checkout', () => {
it('shows new checkout when flag is on', () => {
setFeatureFlag('new-checkout', true);
const checkout = showNewCheckout();
expect(checkout).toBe('<NewCheckout />');
});
it('shows old checkout when flag is off', () => {
setFeatureFlag('new-checkout', false);
const checkout = showNewCheckout();
expect(checkout).toBe('<OldCheckout />');
});
});
// Integration tests with toggles enabled/disabled
describe('Checkout Integration', () => {
it('processes payment when flag is on', async () => {
setFeatureFlag('payments-enabled', true);
const result = await processPayment();
expect(result.success).toBe(true);
});
it('shows maintenance message when flag is off', async () => {
setFeatureFlag('payments-enabled', false);
const result = await processPayment();
expect(result.message).toBe('Maintenance mode');
});
});
// Feature branch testing (toggle on)
describe('Feature Branch Tests', () => {
beforeEach(() => {
setFeatureFlag('new-checkout', true);
});
it('tests new checkout flow', () => {
// Test new checkout flow
});
});
// Multi-variate flags (not just on/off)
const variant = client.variation('new-ui', 'v1', user);
if (variant === 'v1') {
render(<UIVariant1 />);
} else if (variant === 'v2') {
render(<UIVariant2 />);
} else if (variant === 'v3') {
render(<UIVariant3 />);
}
// A/B/C testing
const variant = client.variation('checkout-test', 'A', user);
if (variant === 'A') {
render(<CheckoutVariantA />);
} else if (variant === 'B') {
render(<CheckoutVariantB />);
} else if (variant === 'C') {
render(<CheckoutVariantC />);
}
// Short-lived release toggles (remove after rollout)
function shortLivedToggle() {
// Create toggle
setFeatureFlag('new-checkout', false);
// Use during rollout
// Remove after full rollout
console.log('Toggle will be removed after rollout');
}
shortLivedToggle();
// Long-lived permission toggles (for plans)
function longLivedToggle() {
// Permission toggles stay
setFeatureFlag('premium-feature', true, {
segments: ['premium']
});
console.log('Permission toggle stays for premium users');
}
longLivedToggle();
// Descriptive names (new-checkout, not flag-123)
function descriptiveNames() {
setFeatureFlag('new-checkout', false); // Good
setFeatureFlag('flag-123', false); // Bad
}
descriptiveNames();
// Default to off (safe default)
function defaultToOff() {
setFeatureFlag('new-checkout', false); // Safe default
console.log('Default to off (safe)');
}
defaultToOff();
// Toggle everywhere (overuse)
function toggleEverywhere() {
// Too many toggles
if (featureEnabled('flag-1')) { /* ... */ }
if (featureEnabled('flag-2')) { /* ... */ }
if (featureEnabled('flag-3')) { /* ... */ }
// ... many more
}
toggleEverywhere();
// Not removing old toggles (debt)
function notRemovingOldToggles() {
// Old toggles accumulate
if (featureEnabled('old-feature-1')) { /* ... */ }
if (featureEnabled('old-feature-2')) { /* ... */ }
// ... many old toggles
}
notRemovingOldToggles();
// Complex toggle logic (if A && B && !C...)
function complexToggleLogic() {
// Too complex
if (featureEnabled('flag-A') && featureEnabled('flag-B') && !featureEnabled('flag-C')) {
// ...
}
}
complexToggleLogic();
// Feature rollout with LaunchDarkly
const LaunchDarkly = require('ldclient-node');
const client = LaunchDarkly.init('sdk-key');
client.on('ready', () => {
// Dark launch (off by default)
const flagValue = client.variation('new-checkout', false, user);
// Enable for internal users
client.variation('new-checkout', false, {
key: '[email protected]'
});
// Ramp to 5%
client.variation('new-checkout', false, user, {
percentage: 5
});
// Ramp to 50%
client.variation('new-checkout', false, user, {
percentage: 50
});
// Ramp to 100%
client.variation('new-checkout', false, user, {
percentage: 100
});
});
// A/B test with feature flags
const variant = client.variation('checkout-test', 'A', user);
if (variant === 'A') {
render(<CheckoutVariantA />);
analytics.track('checkout_variant_A_viewed');
} else {
render(<CheckoutVariantB />);
analytics.track('checkout_variant_B_viewed');
}
// Determine winner
const metrics = analytics.getMetrics('checkout-test');
if (metrics.A.conversionRate > metrics.B.conversionRate) {
setFeatureFlag('checkout-test', 'A');
} else {
setFeatureFlag('checkout-test', 'B');
}
// Kill switch for critical feature
function killSwitch() {
// Disable payments if issues
if (paymentGatewayDown) {
setFeatureFlag('payments-enabled', false);
console.log('Payments disabled');
}
}
// Monitor payment gateway
setInterval(() => {
const status = checkPaymentGatewayStatus();
if (status !== 'healthy') {
killSwitch();
}
}, 60000); // Check every minute
---
## Quick Start
### LaunchDarkly Integration
```javascript
const LaunchDarkly = require('launchdarkly-node-server-sdk')
const client = LaunchDarkly.init(process.env.LAUNCHDARKLY_SDK_KEY)
// Check feature flag
const flagValue = await client.variation('new-checkout-flow', user, false)
if (flagValue) {
// New checkout flow
} else {
// Old checkout flow
}
interface FeatureToggle {
name: string
enabled: boolean
percentage?: number
userIds?: string[]
}
class FeatureToggleService {
async isEnabled(toggleName: string, userId: string): Promise<boolean> {
const toggle = await db.featureToggles.findUnique({
where: { name: toggleName }
})
if (!toggle || !toggle.enabled) return false
// Percentage rollout
if (toggle.percentage) {
const hash = this.hashUserId(userId)
return hash % 100 < toggle.percentage
}
// User list
if (toggle.userIds?.includes(userId)) {
return true
}
return false
}
}
// ❌ Bad - Toggle never removed
if (featureToggle('old-feature')) {
// Old code still here!
}
// ✅ Good - Remove after feature stable
// Toggle removed after 2 weeks of 100% rollout
// Old code removed
// ❌ Bad - No fallback
const value = await getToggle('feature')
if (value) {
newFeature() // What if toggle service fails?
}
// ✅ Good - Fallback to safe default
const value = await getToggle('feature').catch(() => false) // Default: off
if (value) {
newFeature()
} else {
oldFeature() // Safe fallback
}
26-deployment-strategies/canary-deployment/) - Gradual rollout23-business-analytics/ab-testing-analysis/) - Feature testing14-monitoring-observability/) - Toggle monitoringxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience