Stable Product Feature Releases through OpenFeature
Introduction
I used to think keeping things simple was best — change the code or flip an environment variable — why introduce more complex package management or third-party services? But in real incidents you don’t have the time to slowly deploy and debug, so it’s necessary to use a more complete Feature Flag strategy to reduce the risk of releasing features and to lower the chance of heart-stopping moments.
So in this article we’ll take a closer look at how to use OpenFeature, an open-source standard, ecosystem, and SDK tooling for Feature Flag practices, to build a smoother and more stable product feature rollout experience.
Current problems
- Development is done but the business side isn’t ready
- Features are distributed across multiple services
- Experimental features
Typically implementing a Feature Flag only requires embedding a variable in the code or using an environment variable. While simple and workable, this approach is hard to manage and track, and cannot flexibly and quickly switch to respond to complex incidents.
const isJira1234FeatureFlagOn = import.meta.env.VITE_Jira_1234if (isJira1234FeatureFlagOn) { // Flag on} else { // Flag off}What is OpenFeature?
OpenFeature is an open-source, multi-vendor-supported open standard for implementing common Feature Flag practices:
OpenFeature glossary
- Evaluation API
- Allows developers to evaluate Feature Flags and use the evaluation result to influence control flow or behavior.
- Evaluation Context
- A container for arbitrary contextual data (e.g.,
user_id,region,email) that can be used as the basis for dynamic evaluations.
- A container for arbitrary contextual data (e.g.,
- Providers
- Responsible for mapping the parameters given to the Evaluation API to their equivalent representation in the associated flag management system. Providers can wrap vendor SDKs, call custom flag evaluation REST APIs, or even parse locally stored files to resolve flag values.
- Hooks
- Used to add arbitrary behavior at different points in the lifecycle.
- Events
- Triggered when the system emits specific events (e.g., Provider ready, flag configuration change, Provider failure). This lets applications react in real time to environmental changes.
How to use OpenFeature?
Using OpenFeature is like “configuring a socket” and “plugging in a plug” — it mainly consists of three steps:
1. Configure a Provider (set up the socket)
import { OpenFeature, InMemoryProvider } from '@openfeature/web-sdk';
const provider = new InMemoryProvider(flagConfig);await OpenFeature.setContext({ user_id: '123' });await OpenFeature.setProviderAndWait(provider);const flagConfig = { 'show-welcome-banner': { disabled: false, variants: { on: true, off: false }, defaultVariant: 'on', // Optional: contextEvaluator determines the flag result based on context // This is a feature specific to InMemoryProvider; other providers typically handle this on the server side. contextEvaluator: (ctx: any) => { if (ctx.user_id === '123') return 'on'; return 'off'; } }, 'button-color': { disabled: false, variants: { green: 'green', red: 'red', gray: 'gray' }, defaultVariant: 'green', contextEvaluator: (ctx: any) => 'green' }, 'retry-count': { disabled: false, variants: { five: 5, ten: 10 }, defaultVariant: 'five' }, 'config-object': { disabled: false, variants: { production: { env: 'production', apis: ['v1', 'v2'], }, dev: { env: 'development', apis: ['v1'], } }, defaultVariant: 'production' },};2. Get a Client (obtain access interface)
Client is the entry point to interact with Feature Flags. You can get different Clients for different business domains (e.g., user-service or billing).
const client = OpenFeature.getClient('my-app-name');3. Perform evaluation (get results)
Use the APIs provided by the Client to obtain flag values. You need to provide the flag name, a default value, and an optional evaluation context.
// Dynamically provide context (such as user ID)const context = { targetingKey: 'user-123', region: 'asia' };
const isNewFeatureEnabled = await client.getBooleanValue( 'new-cool-feature', false, context);
if (isNewFeatureEnabled) { // 執行新功能代碼}Choosing the right solution
Above we used the default official practice InMemoryProvider via the web/sdk in the frontend to get familiar with OpenFeature’s basic workflow. In practice you can choose from many available Providers.
You can also hook up a backend flagConfig to dynamically change Feature Flags:
// Node.js/Expressapp.get('/api/feature-flags', authenticate, (req, res) => { const userId = req.user.id; const userRegion = req.user.region;
const flags = { 'show-welcome-banner': { disabled: false, variants: { on: true, off: false }, defaultVariant: userId === '123' ? 'on' : 'off' } };
res.json(flags);});const response = await fetch('/api/feature-flags', { headers: { 'Authorization': `Bearer ${token}` }});const flagConfig = await response.json();
const provider = new InMemoryProvider(flagConfig);await OpenFeature.setProviderAndWait(provider);Although the above approach works, InMemoryProvider is typically used for testing or static configuration. It’s better to adopt other Feature Flag infrastructures such as flagd and management interfaces like unleash.
// 2. The frontend uses a flagged providerimport { FlagdWebProvider } from '@openfeature/flagd-web-provider';
const provider = new FlagdWebProvider({ host: 'https://your-flagd-server.com', port: 8013});
await OpenFeature.setProviderAndWait(provider);Further reading
- OpenFeature Will CHANGE How You Deploy Code - Better Stack
- An Introduction to Feature Flagging & OpenFeature - CNCF [Cloud Native Computing Foundation]
- Move from Environment Variables to Feature Flags - OpenFeature