unleash Documentation

Open-source feature management platform

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy unleash on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name unleash -p 5432:5432 --restart always postgres:18-alpine
Configured Services & Ports
โš™๏ธ postgres
image: postgres:18-alpine
๐Ÿ”Œ Ports: 5432:5432
โš™๏ธ pgadmin
image: dpage/pgadmin4:9.17
๐Ÿ”Œ Ports: 8080:80
docker-compose.yml
yaml (docker-compose.yml)
version: '3.1'

services:
  postgres:
    image: postgres:18-alpine
    environment:
      POSTGRES_USER: unleash_user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: unleash
    ports:
      - 5432:5432

  pgadmin:
    image: dpage/pgadmin4:9.17
    environment:
      PGADMIN_DEFAULT_EMAIL: '[email protected]'
      PGADMIN_DEFAULT_PASSWORD: 'admin'
    ports:
      - 8080:80

1. Project Overview & Quickstart (Unleash/unleash)

File: README.md

What is Unleash?

Unleash is a powerful open-source solution for feature management. It streamlines your development workflow, accelerates software delivery, and empowers teams to control how and when they roll out new features to end users. With Unleash, you can deploy code to production in smaller, more manageable releases at your own pace.

Feature flags in Unleash let you test your code with real production data, reducing the risk of negatively impacting your users' experience. It also enables your team to work on multiple features simultaneously without the need for separate feature branches.

Unleash is the most popular open-source solution for feature flagging on GitHub. It supports 15 official client and server SDKs and over 15 community SDKs. You can even create your own SDK if you wish. Unleash is compatible with any language and framework.

Get started with Unleash

Set up Unleash

To get started with Unleash, you can either explore Unleash Enterprise with a free trial or get started locally with our open-source solution.

Unleash Enterprise

To start with Unleash Enterprise, request a free trial. This gives you access to a hosted instance with unlimited projects and environments and features such as role-based access control, change requests, single sign-on, and SCIM for automatic user provisioning.

Unleash Open Source

To set up Unleash locally, you'll need git and docker installed on your machine.

Execute the following commands:

bash
git clone [email protected]:Unleash/unleash.git
cd unleash
docker compose up -d

Then point your browser to localhost:4242 and log in using:

  • username: admin
  • password: unleash4all

If you'd rather run the source code in this repo directly via Node.js, see the step-by-step instructions to get up and running in the contributing guide.

Connect your SDK

Find your preferred SDK in our list of official SDKs and import it into your project. Follow the setup guides for your specific SDK.

If you use the docker compose file from the previous step, here's the configuration details you'll need to get going:

  • For frontend SDKs, use:
    • URL: http://localhost:4242/api/frontend/
    • clientKey: default:development.unleash-insecure-frontend-api-token
  • For backend SDKs, use:
    • Unleash API URL: http://localhost:4242/api/
    • API token: default:development.unleash-insecure-api-token

If you use a different setup, your configuration details will most likely also be different.

Check a feature flag

Checking the state of a feature flag in your code is easy! The syntax will vary depending on your language, but all you need is a simple function call to check whether a flag is available. Here's how it might look in Java:

java
if (unleash.isEnabled("AwesomeFeature")) {
  // do new, flashy thing
} else {
  // do old, boring stuff
}

Try Unleash in the cloud

Want to explore Unleash without setting it up locally? Here are two easy ways to see it in action.

Live demo

Open a running Unleash environment in your browser with no signup or setup required. This shared demo instance includes the core functionality so you can quickly get a feel for how Unleash works.

โ†’ Launch the live demo

Free Enterprise trial

Get your own dedicated instance with a free 14-day cloud trial. This includes the full Unleash Enterprise feature set; ideal when evaluating Unleash for production use.

โ†’ Start your free trial

Deploying to a production server

To self-host Unleash in a production environment, you need to deploy it to a persistent server.

We provide guides for deploying to services like Heroku and DigitalOcean:

For more advanced configurations options, check out our documentation on:

Community and help

We know that learning a new tool can be hard and time-consuming. We have a growing community that loves to help out. Please don't hesitate to reach out for help.

๐Ÿ’ฌ Join Unleash on Slack if you want ask open questions about Unleash, feature toggling or discuss these topics in general.

๐Ÿ’ป Create a GitHub issue if you have found a bug or have ideas on how to improve Unleash.

๐Ÿ“š Visit the documentation for more in-depth descriptions, how-to guides, and more.

๐Ÿ“– Learn more about the principles of building and scaling feature flag solutions.

Contribute to Unleash

Unleash is the largest open-source feature flag solution on GitHub. Building Unleash is a collaborative effort, and we owe a lot of gratitude to many smart and talented individuals. Building it together with the community ensures that we build a product that solves real problems for real people. We'd love to have your help too: Please feel free to open issues or provide pull requests.

Check out the CONTRIBUTING.md file for contribution guidelines and the Unleash developer guide for tips on environment setup, running the tests, and running Unleash from source. Before a pull request can be merged, contributors must read and agree to the Unleash Contributor License Agreement.

Contributors

Documentation

You can visit the Unleash documentation at https://docs.getunleash.io. As of 2 February 2026, the Unleash documentation source code lives in its own repository: Unleash/unleash-documentation.

Features our users love

Flexibility and adaptability

Security and performance

  • Privacy by design (GDPR and Schrems II). End-user data never leaves your application.
  • Audit logs
  • Enforce OWASP's secure headers via the strict HTTPS-only mode
  • Flexible hosting options: host it on premise or in the cloud (any cloud)
  • Scale with Unleash Edge independently of the Unleash server to support any number of frontend clients without overloading your Unleash instance

Looking for more features?

If you're looking for one of the following features, please take a look at our Pro and Enterprise plans:

Architecture

Read more in the system overview section of the Unleash documentation.

Unleash SDKs

To connect your application to Unleash you'll need to use a client SDK for your programming language.

Official backend SDKs:

Official frontend SDKs:

Community SDKs:

If none of the official SDKs fit your need, there's also a number of community-developed SDKs where you might find an implementation for your preferred language (such as Elixir, Dart, Clojure, and more).

Users of Unleash

Unleash is trusted by thousands of companies all over the world.

Proud Open-Source users: (send us a message if you want to add your logo here)

Migration guides

Unleash has evolved significantly over the past few years, and we know how hard it can be to keep software up to date. If you're using the current major version, upgrading shouldn't be an issue. If you're on a previous major version, check out the Unleash migration guide!

Want to know more about Unleash?

Videos and podcasts

Articles and more


File: frontend/cypress/README.md

Unleash Behavioural tests

Add common commands to Cypress

  • global.d.ts is where we extend Cypress types
  • API.ts contains api requests for common actions (great place for cleanup actions)
  • UI.ts contains common functions for UI operations
  • commands.ts is the place to map the functions to a cypress command

Test Format

Ideally each test should manage its own data.

Avoid using after and afterEach hooks for cleaning up. According to Cypress docs, there is no guarantee that the functions will run

Suggested Format:

  • prepare
  • when
  • then
  • clean

Passing (returned) parameters around

ts
it('can add, update and delete a gradual rollout strategy to the development environment', async () => {
    cy.addFlexibleRolloutStrategyToFeatureUI({
        featureToggleName,
    }).then(value => {
        strategyId = value;
        cy.updateFlexibleRolloutStrategyUI(featureToggleName, strategyId).then(
            () => cy.deleteFeatureStrategyUI(featureToggleName, strategyId)
        );
    });
});

File: frontend/src/component/impact-views/README.md

Impact Views (experimental)

Impact views let a user follow a set of feature flags and their impact metrics
together on a single chart.

The full feature (built on the feat/exp-views branch) includes goal-tracking
and system-health templates, a "top flag movers" panel, a flag-impact dialog, and a
view editor. We are re-introducing it onto main incrementally. The current,
narrowed scope is a basic goal-tracking view with dummy data
โ€” see "Rollout plan"
for what is in scope now vs. deferred.

This feature is experimental and intentionally not production-hardened:

  • Storage is browser localStorage โ€” there is no backend persistence, no
    new database tables, and no new API endpoints. The getters used here hit
    existing endpoints only (e.g. api/admin/search/events).
  • It is gated behind the impactViews feature flag and served from the
    self-contained /impact-views route.
  • Everything is co-located under this directory so the feature can be
    removed cleanly (see "Deletion contract" below).

Layout

text
component/impact-views/
  ImpactViewsPage.tsx        # page: switcher + active view's chart (useGoalViewData)
  LazyImpactViewsPage.tsx    # lazy wrapper used by the route
  views/                     # components (GoalSummaryPanel, MultimetricChartCard, FollowedFeaturesList,
                             #   ViewSwitcher, FeaturePicker, ViewEditorDialog, ImpactMetricViewsEmptyState, โ€ฆ)
  hooks/                     # data hooks (useGoalViewData seam + resolver/event/metrics hooks)
                             #   + useImpactMetricViews (localStorage CRUD)

Reused from main (imported, not copied): the MultimetricChart suite
(chartConfig, types, FeatureEventOverlay/eventTheme, MultimetricTotals),
metricsFormatters, useFeatureEnvironmentEvents, useImpactMetricsMetadata
(useImpactMetricsOptions), useEnvironments, useFeatureSearch,
useLocalStorageState, createUuid, PageHeader, PageContent, LineChart,
FeatureLifecycleStageIcon.

Rollout plan (small, independently-mergeable PRs)

Source of the view files: the feat/exp-views branch under
frontend/src/component/impact-metrics/views/. Extract file contents (not
commits โ€” the branch carries unrelated churn) and adjust import paths to the
co-located locations.

Current focus: the view editor + localStorage CRUD โ€” let users create/edit/switch/delete
their own views, persisted in browser localStorage. The basic goal-tracking view already
renders real sandbox data. See "Status" and the "NEXT" section below for exactly where to
resume.

Scope is goal-tracking only. Still deferred (revisit later): the system-health view,
the Top Movers panel and the Flag Impact dialog (and the flag-event impact math behind
them), and the synthetic-data generators.

PR Contents
1 โœ… impactViews flag (backend experimental.ts + frontend UiFlags), /impact-views route, gated nav item, stub page + this README.
2 Goal-view types + goal summary (no components, no API calls): views/types.ts, computeGoalSummary(+test).
3 Goal summary panel (render-only): GoalSummaryPanel. (FollowedFeaturesStrip dropped โ€” dead code, nothing imports it.)
4 Chart card (render-only layout): views/MultimetricChartCard/MultimetricChartCard.tsx. (Getter useGroupedImpactMetricsData deferred to the real-data PR โ€” not needed for dummy data.)
5 Followed-features list (render-only): views/FollowedFeaturesList/FollowedFeaturesList.tsx, rendered below the card on the page with dummy feature names. (The GoalTrackingViewChart orchestrator and useMergedFeatureEvents stay with the deferred real-data wiring โ€” they exist to fetch live data the dummy view doesn't need.)
(later) Replace the per-piece dummy wiring on ImpactViewsPage with a single cohesive dummy goal view / GoalTrackingViewChart if desired โ€” optional polish, no new components.
Deferred Top Movers / Flag Impact (computeFlagEventImpact, flagImpactFormatting, TopFlagMoversPanel, FlagImpactDialog); real-data wiring; view editor + localStorage CRUD (ViewEditorDialog, useImpactMetricViews, FeaturePicker, TemplatePickerDialog, ViewSwitcher, ImpactMetricViews); system-health view (SystemHealthViewChart, ViewChart template router, useAutoFollowedFeatureNames, useEnvironmentEvents, normalizeSeriesToBaseline); the synthetic generator simulateFlagContribution.

Status

  • PR 1 โ€” merged (#12173). Flag, route, nav, stub page, this README.
  • PR 2 โ€” merged (#12177). views/types.ts + views/computeGoalSummary.ts(+test).
  • PR 3 โ€” merged. views/GoalSummaryPanel/ (panel + extracted, tested sparkline.ts).
    (Shipped with a throwaway dummy preview that was later replaced by real data in PR 6.)
  • PR 4 โ€” merged. views/MultimetricChartCard/MultimetricChartCard.tsx (render-only layout
    card, prop interface tightened to what the goal view needs). The page now renders the card
    with dummy data and the GoalSummaryPanel in its totalsHeaderSlot. Note: the branch
    version passed highlightedEventId / eventImpactById to <MultimetricChart> and exported
    FeatureEventImpactSummary โ€” those MultimetricChart props are branch-only additions
    (deferred Top Movers / event-tooltip work), NOT on main, so they were stripped from the
    co-located card. When Top Movers lands, re-add them to both MultimetricChart and this card.
  • PR 5 โ€” merged. views/FollowedFeaturesList/FollowedFeaturesList.tsx rendered below the
    chart card. Made presentational: it takes features: ResolvedFeature[] and only groups
    • renders them (data fetching deferred to the real-data phase). Trimmed (550 โ†’ ~310) and
      refactored into StageBadge/GroupHeaderRow/FeatureRow. Labels come from the shared
      getFeatureLifecycleName. PageContent wrapper removed from the page.
  • PR 6 โ€” merged. Real data from a hardcoded view template. The page is data-driven:
    useGoalViewData(view) fans out to live getters and feeds the card/panel/list. Pieces (all
    hooks under hooks/):
    • fixtures/goalViewConfig.ts โ€” GOAL_VIEW (purchases goal + error_rate, count/
      month; flags impact-views-1/2/3). Project-agnostic โ€” a view holds only
      featureNames; each flag's project is resolved from the flag itself (no project on
      MetricView). id/createdAt/updatedAt stay required (GOAL_VIEW stubs them).
      (This fixture was removed in PR C once localStorage-backed user views replaced the seed data.)
    • hooks/useGoalViewData.ts (+.test.tsx) โ€” composition seam (the only file the page calls).
      Picks the goal series/total by the goal metric's index (not [0]); handles empty series.
    • hooks/useResolvedFeatures.ts โ€” featureNames โ†’ ResolvedFeature[] via one
      cross-project
      useFeatureSearch({ query: names.join(',') }) (backend โ†’ name ILIKE ANY),
      filtered client-side by exact name. (feature-search limit capped at 100 server-side.)
    • hooks/useFollowedFeatureEvents.ts โ€” all flags' toggle events in one cross-project
      request via the shared useEventSearch getter (feature: IS_ANY_OF:โ€ฆ), mapped for the
      chart overlay. No per-flag loaders.
    • Chart/totals/window from on-main useGroupedImpactMetricsData(view.metrics); goal summary
      from computeGoalSummary.
    • Architecture: each data concern is its own small hook behind a narrow interface (all
      under hooks/); the page has no fetching logic.

Editor + localStorage CRUD (goal-tracking only) โ€” โœ… COMPLETE

Users create/edit/switch/duplicate/delete their own views, persisted in browser localStorage.
Extracted from feat/exp-views:.../views/, stripping template/system-health/normalize/
autoFollowFlags. 4 PRs, all merged:

  • PR A โ€” View switcher (views/ViewSwitcher/). Page held activeViewId and rendered the
    active view via useGoalViewData. (Seeded from a temporary DUMMY_VIEWS fixture, since removed.)
  • PR B1 โ€” views/FeaturePicker/FeaturePicker.tsx โ€” MUI <Autocomplete multiple>, 250ms debounce.
  • PR B2 โ€” views/ViewEditorDialog/ViewEditorDialog.tsx (goal-only create/edit form, shared
    Dialogue chrome, single view-level aggregation via GeneralSelect, useReducer form state) +
    page wiring (in-memory create/edit via the editor discriminated union).
  • PR C โ€” hooks/useImpactMetricViews.ts (localStorage CRUD: keys impact-metric-views:list /
    impact-metric-views:active-id, via useLocalStorageState + createUuid, real Date.now()
    timestamps) + hooks/useImpactMetricViews.test.tsx + views/ImpactMetricViewsEmptyState/.
    Page now uses the hook (no more in-memory state / DUMMY_VIEWS): empty storage โ†’ empty-state CTA;
    delete โ†’ shared Dialogue confirm; duplicate โ†’ duplicateView. The goalViewConfig.ts fixture
    was deleted (dead once localStorage landed).

NEXT: deferred work (revisit when prioritized)

The editor phase is done. Remaining deferred items (not yet started) โ€” see the table above and
"Decisions & context" below:

  • Top Movers / Flag Impact โ€” computeFlagEventImpact(+test), flagImpactFormatting,
    TopFlagMoversPanel, FlagImpactDialog (re-extract from feat/exp-views; not on main).
  • System-health view โ€” SystemHealthViewChart, ViewChart template router,
    useAutoFollowedFeatureNames, useEnvironmentEvents, normalizeSeriesToBaseline.
  • Synthetic generator simulateFlagContribution.

Extraction mechanic unchanged: git show feat/exp-views:.../<file> โ†’ strip
template/system-health/normalize/autoFollowFlags + comments โ†’ point imports at on-main modules.

Decisions & context (for picking this up later)

  • Real data is live โ€” the goal view renders real sandbox data (PR 6). All dummy fixtures
    (including the DUMMY_VIEWS/GOAL_VIEW goalViewConfig.ts) have been removed; views are now
    user-created and persisted in localStorage (PR C).
  • No backend work is needed; getters hit existing endpoints. If an extracted file imports
    a symbol not on main, add the smallest co-located copy rather than editing shared/backend
    code.
  • types.ts is trimmed to goal-tracking-only (MetricView, ViewMetricConfig). The
    template machinery (ViewTemplate/TEMPLATE_DEFAULTS/DEFAULT_VIEW_*), localStorage keys,
    and default env/timeRange constants were removed โ€” they come back (re-extracted + stripped of
    system-health) with the editor/CRUD PRs. MetricView has no project (project-agnostic;
    resolved per-flag) and keeps id/createdAt/updatedAt required.
  • Cross-project, one-request data fetching โ€” the resolver and event hooks deliberately
    avoid per-flag requests + per-project filters; they query all followed flags at once
    (query: names.join(',') / feature: IS_ANY_OF:โ€ฆ). Keep this pattern when extending.
  • PR-2 history note: PR 2 originally bundled the flag-impact math; it was split into a
    stacked "PR 2b" (#12178) which was then closed when Top Movers / Flag Impact was
    deferred. So computeFlagEventImpact(+test) and flagImpactFormatting are not yet on
    main โ€” re-extract them from feat/exp-views when picking up Top Movers.
  • Extraction mechanic: git show feat/exp-views:frontend/src/component/impact-metrics/views/<file>
    โ†’ write into views/, then point imports at the on-main shared modules (and at
    co-located ../hooks/ once PR 4 lands). Keep extracted files close to their branch
    originals to ease later wiring.

Flag wiring

  • Backend: impactViews in src/lib/types/experimental.ts
    (env var UNLEASH_EXPERIMENTAL_IMPACT_VIEWS, default false).
  • Frontend: impactViews in frontend/src/interfaces/uiConfig.ts (UiFlags).
  • Route: /impact-views in frontend/src/component/menu/routes.ts (flag: 'impactViews').
  • Nav: gated PrimaryListItem in
    frontend/src/component/layout/MainLayout/NavigationSidebar/NavigationList.tsx.

Deletion contract

Removing the feature is: delete this component/impact-views/ directory, the one
/impact-views entry in routes.ts, the gated nav line in NavigationList.tsx,
and the two impactViews flag declarations (backend + frontend).


File: frontend/README.md

frontend

This directory contains the Unleash Admin UI frontend app.

Run with a local instance of the unleash-api

Refer to the Contributing to Unleash guide for instructions.
The frontend dev server runs (in port 3000) simultaneously with the backend dev server (in port 4242):

text
pnpm install
pnpm dev

Run with a sandbox instance of the Unleash API

Alternatively, instead of running unleash-api on localhost, you can use a remote instance:

text
cd ./frontend
pnpm install
pnpm run start:sandbox

Running end-to-end tests against localhost

If you need to test against a local server instance,
you'll need to run in the root directory:

  • pnpm build:frontend
  • pnpm dev:start

Then run the e2e tests using:

text
pnpm run e2e

You may also need to test that a feature works against the enterprise version of unleash.

text
pnpm run start:enterprise
pnpm run e2e:enterprise

Debugging end-to-end tests

Run backend and frontend in development build. In the root of the project run e.g.: pnpm dev.

Please keep in mind that running tests against dev frontend will be really slow (even x5 slower).
It's best to open cypress UI and pick only the test that you need to work on.

In frontend project run:

text
pnpm e2e:dev:open

Generating the OpenAPI client

The frontend uses an OpenAPI client generated from the backend's OpenAPI spec.
Whenever there are changes to the backend API, the client should be regenerated:

For now we only use generated types (src/openapi/models).
We will use methods (src/openapi/apis) for new features soon.

text
pnpm gen:api
rm -rf src/openapi/apis

clean up src/openapi/index.ts imports, only keep first line export * from './models';

This script assumes that you have a running instance of the enterprise backend at http://localhost:4242.
The new OpenAPI client will be generated from the runtime schema of this instance.
The target URL can be changed by setting the UNLEASH_OPENAPI_URL env var.

Analyzing bundle size

npx vite-bundle-visualizer in the root of the frontend directory

2. Official Technical Reference & Guides (Unleash/unleash-documentation)

Unleash Documentation

What is Unleash?

Unleash is a powerful open-source solution for feature management. It streamlines your development workflow, accelerates software delivery, and empowers teams to control how and when they roll out new features to end users. With Unleash, you can deploy code to production in smaller, more manageable releases at your own pace.

Feature flags in Unleash let you test your code with real production data, reducing the risk of negatively impacting your users' experience. It also enables your team to work on multiple features simultaneously without the need for separate feature branches.

Unleash is the most popular open-source solution for feature flagging on GitHub. It supports 15 official client and server SDKs and over 15 community SDKs. You can even create your own SDK if you wish. Unleash is compatible with any language and framework.

Try Unleash Enterprise for free

About this repository

This repository contains the source code for the official Unleash documentation. The site is built entirely by the Fern CLI.

API specs are committed to the repo and kept up to date by CI โ€” you don't need to fetch them locally.

Quickstart

Prerequisites

  • Node.js 20+ (required to install and run the Fern CLI)
  • Fern CLI: npm install fern-api

Clone and run

bash
git clone https://github.com/Unleash/unleash-documentation.git
cd unleash-documentation
fern docs dev

That's it. The dev server starts at http://localhost:3000.

Command reference

Command What it does
fern docs dev Starts the local dev server.
fern check --strict-broken-links Validates the documentation and checks for broken links.
node scripts/fetch-openapi.mjs Manually refreshes the API specs from the hosted Unleash and Unleash Edge instances. Only needed if you want newer specs than what's committed.

How API specs are updated

CI automatically fetches the latest OpenAPI specs from hosted Unleash and Unleash Edge instances on every push to main and every PR. The Unleash spec is split into three domains to keep the API reference navigable, and the Edge spec is published as its own reference:

  • Admin API (fern/apis/admin-api/): All endpoints except Client and Frontend.
  • Client API (fern/apis/client-api/): Client-tagged endpoints only.
  • Frontend API (fern/apis/frontend-api/): Frontend API-tagged endpoints only.
  • Unleash Edge API (fern/apis/edge-api/): Client and Frontend compatible endpoints exposed by Unleash Edge.

You only need to run node scripts/fetch-openapi.mjs locally if you're working on API reference content and need a spec that's newer than the last CI run.

How last-updated dates work

A GitHub Action (.github/workflows/update-last-updated.yml) runs on every pull request and automatically adds or updates a last-updated field in the YAML frontmatter of any changed MDX file. You don't need to set this manually.

Architecture

  • Engine: Fern
  • API specs: OpenAPI JSON files in fern/apis/, fetched by CI from a hosted Unleash instance
  • Custom footer: React component (fern/components/CustomFooter.tsx), server-side rendered by Fern
  • Custom styling: CSS overrides in fern/styles.css. For detailed architecture notes and conventions, see CLAUDE.md.

Contributing

We welcome contributions. If you find something that's wrong, unclear, or missing, feel free to open an issue or submit a pull request.

  1. Fork and clone this repository.
  2. Create a new branch for your changes.
  3. Run fern docs dev to preview locally.
  4. Submit a pull request.

For contributions to the Unleash product itself, see the main Unleash repository.

Migration history

This documentation was migrated to its own repository on 2 February 2026. It previously lived in the website folder of the main Unleash repository.

You can find the commit history prior to the migration date in the Unleash/unleash repository.