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 URL

  • UNLEASH_APP_NAME — Application identifier (e.g., ska-tango-examples)

  • UNLEASH_ENVIRONMENT — Current environment (development, staging, production)

  • UNLEASH_INSTANCE_ID — Unique instance identifier

  • UNLEASH_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:

  1. The Proxy runs in your backend infrastructure

  2. The Proxy connects to the Unleash server using a secure server-side token

  3. Your React app connects to the Proxy using a less sensitive client key

  4. 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.