Feature Flags Tutorial#
Learn to implement feature flags in Python and React applications.
This tutorial covers two implementation paths:
Python SDK — For backend services and Tango devices
React Proxy Client — For frontend web applications
Read How Feature Flags Work first to understand feature flag concepts and decide which implementation suits your needs.
Python SDK Tutorial#
Integrate feature flags into a Python project using the Unleash Python SDK v5.x.
Note
This tutorial uses ska-tango-examples as an example, but the same principles apply to any Python project.
Prerequisites#
Python 3.10 or later
Poetry for dependency management
Docker
Helm (v3) and a Kubernetes cluster
Access to GitLab Feature Flags with:
Unleash server URL (
UNLEASH_URL)Unleash Instance ID (
UNLEASH_INSTANCE_ID)
For Unleash server credentials, follow the GitLab Feature Flags documentation and the “Get access credentials” section.
Install the SDK#
Add the Unleash Python SDK to your project:
poetry add UnleashClient
Commit the updated pyproject.toml and poetry.lock files.
Configure environment variables#
Make the Unleash client configurable via environment variables to support multiple deployment environments:
UNLEASH_URL— Unleash API server URLUNLEASH_APP_NAME— Application identifier (e.g.,ska-tango-examples)UNLEASH_ENVIRONMENT— Current environment (development,staging,production)UNLEASH_INSTANCE_ID— Unique instance identifierUNLEASH_REFRESH_INTERVAL— Flag refresh interval in seconds (default: 15)
Set these via Kubernetes ConfigMaps/Secrets for deployments, or a .env file for local development.
Configure Helm values#
Add Unleash configuration to your Helm chart’s values.yaml:
unleash:
url: "https://gitlab.com/api/v4/feature_flags/unleash/9673989"
appName: "ska-tango-examples"
environment: "development"
refreshInterval: 15
idSecretName: "ska-tango-examples-unleash-id"
idSecretKey: "unleash-instance-id"
Store the Instance ID securely using the Vault Secrets Operator. See Vault for details.
Initialise the client#
Create a feature toggler class that initialises the Unleash client:
import logging
import os
from UnleashClient import UnleashClient
logger = logging.getLogger(__name__)
class FeatureToggler:
def __init__(self):
self.init_feature_toggler()
self.initialized = True
def init_feature_toggler(self) -> None:
"""Initialise the Unleash client."""
if "UNLEASH_INACTIVE" not in os.environ:
try:
self.unleash_client = UnleashClient(
url=os.environ["UNLEASH_API_URL"],
app_name=os.getenv("UNLEASH_ENVIRONMENT", default="development"),
instance_id=os.environ["UNLEASH_INSTANCE_ID"],
disable_metrics=True,
disable_registration=True,
verbose_log_level=logger.getEffectiveLevel(),
refresh_interval=60,
)
self.unleash_client.initialize_client()
except Exception as e:
logger.error("Error initialising feature toggler: %s", e)
Instantiate the toggler early in your application’s initialisation:
self._feature_toggler = FeatureToggler().unleash_client
Check flag status#
Use is_enabled to check if a feature is active:
if self._feature_toggler.is_enabled(
"timer-double-increment",
fallback_function=lambda: False
):
self._value += 2
else:
self._value += 1
Always provide a fallback_function to handle cases where the Unleash server is unreachable.
React Proxy Client Tutorial#
Integrate feature flags into a React application using the Unleash Proxy Client.
Warning
Never use the Unleash client directly in browser applications. The Proxy Client communicates securely with an Unleash Proxy, which protects your server-side API tokens.
Why use the Unleash Proxy?#
Frontend applications cannot securely store server-side API tokens. The Unleash Proxy acts as a secure intermediary:
The Proxy runs in your backend infrastructure
The Proxy connects to the Unleash server using a secure server-side token
Your React app connects to the Proxy using a less sensitive client key
The Proxy evaluates flags and returns results to the frontend
Warning
SKAO does not run a central managed Proxy Server. Deploy your own Proxy and configure it to connect to the upstream Unleash Server. Contact the System Team if you need assistance.
Prerequisites#
Node.js and Yarn
Docker and container registry access
Helm (v3) and a Kubernetes cluster
A running Unleash Proxy with:
Proxy URL
Proxy client key (if required)
Vault Secrets Operator (VSO) for managing secrets
Install the SDK#
Add the Unleash React Proxy Client:
yarn add @unleash/proxy-client-react
Rebuild your OCI image after updating dependencies.
Configure environment variables#
Add these variables to your env_config file:
REACT_APP_UNLEASH_PROXY_URL:string:http://localhost:3000/proxy
REACT_APP_UNLEASH_APP_NAME:string:ska-react-webapp-skeleton
REACT_APP_UNLEASH_ENVIRONMENT:string:development
REACT_APP_UNLEASH_CLIENT_KEY:string:
REACT_APP_UNLEASH_REFRESH_INTERVAL:number:30
REACT_APP_UNLEASH_DISABLE_METRICS:boolean:false
Create a context provider#
Initialise the Unleash client using a React Context Provider:
// src/contexts/FeatureFlagProvider.tsx
import React, { ReactNode } from 'react';
import { FlagProvider } from '@unleash/proxy-client-react';
import { env } from '../env';
interface FeatureFlagProviderProps {
children: ReactNode;
}
const config = {
url: env.REACT_APP_UNLEASH_PROXY_URL,
clientKey: env.REACT_APP_UNLEASH_CLIENT_KEY || 'dummy-key',
refreshInterval: env.REACT_APP_UNLEASH_REFRESH_INTERVAL || 30,
appName: env.REACT_APP_UNLEASH_APP_NAME || 'ska-react-webapp-skeleton',
environment: env.REACT_APP_UNLEASH_ENVIRONMENT || 'development',
disableMetrics: env.REACT_APP_UNLEASH_DISABLE_METRICS || false,
};
export const FeatureFlagProvider: React.FC<FeatureFlagProviderProps> = ({ children }) => {
return (
<FlagProvider config={config}>
{children}
</FlagProvider>
);
};
Wrap your application#
Add the provider to your application’s root:
// src/index.jsx
import { FeatureFlagProvider } from './contexts/FeatureFlagProvider';
root.render(
<React.Suspense fallback={<Loader />}>
<StoreProvider>
<AuthProvider {...authProps}>
<FeatureFlagProvider>
<App />
</FeatureFlagProvider>
</AuthProvider>
</StoreProvider>
</React.Suspense>
);
Check flag status#
Use the useFlag hook in your components:
import React from 'react';
import { useFlag } from '@unleash/proxy-client-react';
const MyComponent: React.FC = () => {
const showNewFeature = useFlag('my-new-feature-flag');
return (
<div>
{showNewFeature ? (
<p>Showing the new feature!</p>
) : (
<p>Showing standard behaviour.</p>
)}
</div>
);
};
Update context dynamically#
Update the Unleash context when user information changes:
import { useUnleashContext } from '@unleash/proxy-client-react';
import { useMsal } from '@azure/msal-react';
const UserComponent: React.FC = () => {
const updateContext = useUnleashContext();
const { accounts } = useMsal();
const userId = accounts.length > 0 ? accounts[0].username : undefined;
useEffect(() => {
if (userId) {
updateContext({ userId: userId });
}
}, [userId, updateContext]);
// ... component content
};
Coming soon#
Tutorials in development:
Static Configuration — Feature flags via deployment configuration
Tango Framework — Feature flags for Tango devices
Contribute by following the /contribute/style-guide.