Ecosystem/18feature-flags
feature-flags
GitHub: Stackbilt-dev/feature-flags · MIT
Part of the Stackbilt ecosystem. High-performance feature flag system for Cloudflare Workers with <5ms evaluation latency. KV-backed, Hono middleware included, audit logging built in.
Install
npm install @stackbilt/feature-flags
Add KV namespaces to wrangler.toml:
[[kv_namespaces]]
binding = "FEATURE_FLAGS_KV"
id = "your-flags-kv-id"
[[kv_namespaces]]
binding = "FEATURE_FLAGS_CACHE"
id = "your-cache-kv-id"
Quick Start
import { createProductionFeatureFlags, createFeatureFlagMiddleware } from '@stackbilt/feature-flags';
import { Hono } from 'hono';
const app = new Hono();
const flagSystem = createProductionFeatureFlags(env);
app.use('*', createFeatureFlagMiddleware({ manager: flagSystem.manager }));
app.get('/api/data', async (c) => {
const flags = c.get('featureFlags');
const useNew = await flags.isEnabled('new_feature');
return c.json({ data: useNew ? getNewData() : getLegacyData() });
});
Flag Types
Boolean flags
Simple on/off toggles:
await manager.createFlag({ key: 'dark_mode', type: 'boolean', enabled: true });
const isOn = await flags.isEnabled('dark_mode');
Percentage rollouts
Consistent user assignment across requests:
await manager.createFlag({
key: 'new_dashboard',
type: 'percentage',
percentage: 25, // 25% of users
});
Variant flags (A/B/n testing)
await manager.createFlag({
key: 'checkout_flow',
type: 'variant',
variants: [
{ key: 'control', weight: 50 },
{ key: 'streamlined', weight: 30 },
{ key: 'one_page', weight: 20 },
],
});
const variant = await flags.getVariant('checkout_flow');
// Returns 'control' | 'streamlined' | 'one_page' based on user hash
Canary Deployments
Staged rollouts with automatic advancement:
import { createCanaryFlags } from '@stackbilt/feature-flags';
const { gradualRollout, canaryConfig } = createCanaryFlags();
await manager.createFlag(gradualRollout);
// Start at 5%, auto-advance through stages: 5% → 10% → 25% → 50% → 100%
await manager.startCanaryDeployment('gradual_rollout_feature', canaryConfig);
// Manual advance
await manager.updateCanaryDeployment('gradual_rollout_feature', { percentage: 25 });
// Emergency rollback
await manager.stopCanaryDeployment('gradual_rollout_feature');
Tenant Overrides
Per-tenant flag values for multi-tenant deployments:
// Override for a specific tenant
await manager.setTenantOverride('tenant-123', 'new_feature', true);
// Evaluate with tenant context
const flags = manager.forTenant('tenant-123');
const isOn = await flags.isEnabled('new_feature'); // uses override
Rule Engine
Target by tenant, user, IP, custom attributes, or time windows:
await manager.createFlag({
key: 'beta_feature',
type: 'boolean',
rules: [
{ attribute: 'plan', operator: 'equals', value: 'pro', result: true },
{ attribute: 'country', operator: 'in', value: ['US', 'CA'], result: true },
{ attribute: 'created_at', operator: 'after', value: '2026-01-01', result: false },
],
default: false,
});
Admin API
REST endpoints for flag management (auth-gated):
| Method | Path | Description |
|---|---|---|
GET |
/flags |
List all flags |
POST |
/flags |
Create a flag |
PATCH |
/flags/:key |
Update a flag |
DELETE |
/flags/:key |
Delete a flag |
GET |
/flags/:key/metrics |
Evaluation counts + variant distribution |
POST |
/flags/:key/canary/start |
Start canary deployment |
POST |
/flags/:key/canary/stop |
Rollback canary |
Metrics
Evaluation metrics per flag:
const metrics = await manager.getMetrics('checkout_flow');
// {
// evaluations: 42000,
// variants: { control: 21200, streamlined: 12600, one_page: 8200 },
// p50LatencyMs: 2.1, p99LatencyMs: 4.8
// }
All flag changes are written to an audit log in KV with timestamps and actor identity.