Skip to content

How to add feature flags via Flipper

Ian Johnson edited this page Dec 2, 2025 · 4 revisions

Feature Flags with Flipper

We use the Flipper gem to manage feature flags. Flipper lets us:

  • Turn features on/off without deploying
  • Gradually roll out changes
  • Target specific users or organizations

This page covers:

  1. How to access the Flipper UI
  2. How to create a flag
  3. How to use a flag in code
  4. How to target a subset of users or orgs

1. Accessing the Flipper UI

1.1 URL

The Flipper UI is mounted in our Rails routes. By default, it’s available at: /flipper

If that path doesn’t load, check config/routes.rb for the mount:

# config/routes.rb
require "flipper/ui"

Rails.application.routes.draw do
  # ...
  mount Flipper::UI.app(Flipper) => "/flipper"
end

1.2 Authentication / Access control

Typically, the Flipper UI should only be accessible to admins or in non-production environments.

A common pattern:

# config/routes.rb
require "flipper/ui"

flipper_app = Flipper::UI.app(Flipper) do |builder|
  builder.use Rack::Auth::Basic do |username, password|
    # Simple example; replace with real auth
    username == ENV["FLIPPER_USER"] && password == ENV["FLIPPER_PASSWORD"]
  end
end

Rails.application.routes.draw do
  mount flipper_app => "/flipper"
end

Or we mount it only in certain environments:

if Rails.env.development? || Rails.env.staging?
  mount Flipper::UI.app(Flipper) => "/flipper"
end

2. Creating a Feature Flag

You can create flags either through the UI or in code. The UI is preferred for most use cases.

2.1 Creating a flag via the UI

  1. Go to /flipper
  2. On the main page, look for a field labeled “Add Feature” or similar.
  3. Enter a feature key (lowercase, snake_case is typical), e.g.:
    • new_dashboard
    • beta_checkout
    • org_billing_v2
  4. Click Add / Create.

The feature will now appear in the list, and you can configure its “gates” (who gets the feature).

2.2 Creating a flag in code (optional)

You don’t have to pre-create a feature in code—Flipper lazily creates it when referenced—but for clarity you might see code like:

Flipper[:new_dashboard] # creates the feature record if it doesn't exist

This is enough to make Flipper aware of the feature; you still control who gets it via UI or gates.


3. Using a Feature Flag in Code

Once a flag exists, you can check it anywhere in your Rails app.

Assumptions:

  • User (or another model) responds to flipper_id (often implemented as id or "User:#{id}").
  • You have access to current_user (or an equivalent).

3.1 Controllers

class DashboardsController < ApplicationController
  def show
    if Flipper.enabled?(:new_dashboard, current_user)
      render :new_dashboard
    else
      render :old_dashboard
    end
  end
end

3.2 Views

<% if Flipper.enabled?(:new_dashboard, current_user) %>
  <%= render "dashboards/new" %>
<% else %>
  <%= render "dashboards/old" %>
<% end %>

3.3 Background jobs / services

If you don’t have a current_user, pass in whatever actor makes sense (a user, org, or something with a flipper_id):

def perform(user_id)
  user = User.find(user_id)

  return unless Flipper.enabled?(:new_onboarding_flow, user)

  NewOnboardingService.call(user)
end

If you only want a simple global flag (on for everyone or no one), you can omit the actor:

if Flipper.enabled?(:maintenance_mode)
  # ...
end

4. Targeting a Subset of Users or Orgs

Flipper has several “gates” to control who sees a feature:

  • Boolean: on/off for everyone
  • Actors: specific users/orgs
  • Groups: logical groups like :admins
  • Percentage of actors: random rollout to a percentage of users
  • Percentage of time: random rollout based on request time (less common for us)

We primarily use:

  • Specific users/orgs
  • Groups (e.g., admins)
  • Percentage of actors (gradual rollout)

4.1 Making models “Flipper actors”

By default, Flipper looks for #flipper_id on any object you pass as the second argument.

Example implementation on User:

class User < ApplicationRecord
  def flipper_id
    "User;#{id}"
  end
end

For organizations:

class Organization < ApplicationRecord
  def flipper_id
    "Organization;#{id}"
  end
end

Important: Use a namespaced flipper_id ("User;#{id}", "Org;#{id}") to avoid collisions.

4.2 Enabling a flag for specific users

Via UI

  1. Go to /flipper
  2. Click the feature (e.g. new_dashboard)
  3. In the Actors section, add a user by their flipper_id
    • e.g. User;123
  4. Save.

Only those users will see the feature, assuming the “boolean” gate is off.

Via code (if needed)

user = User.find(123)
Flipper[:new_dashboard].enable(user)  # enable for this specific user

You can see this change reflected in the UI as well.

4.3 Enabling a flag for specific organizations

If your app is org-based, you can pass the org as the actor:

org = Organization.find_by!(slug: "acme-corp")

if Flipper.enabled?(:org_billing_v2, org)
  BillingV2::Processor.new(org).run
else
  BillingV1::Processor.new(org).run
end

In the UI:

  • Under Actors, add Organization;ID for the org’s flipper_id.

This lets you roll out a feature org-by-org.

4.4 Using groups (e.g., admins, internal, beta testers)

Flipper supports logical groups defined in code:

Flipper.register(:admins) do |actor|
  actor.respond_to?(:admin?) && actor.admin?
end

Now you can enable a feature for that group:

Flipper[:new_dashboard].enable_group(:admins)

Or via UI:

  1. Open the feature
  2. Under Groups, enable admins

Anywhere you check the flag with a user:

Flipper.enabled?(:new_dashboard, current_user)

Admins will automatically get the feature.

You can define multiple groups, such as :internal, :beta_testers, etc., as long as you register them with a block.

4.5 Percentage rollout (subset of users)

To softly roll out to a percentage of users:

  1. Go to /flipper
  2. Click the feature
  3. Under Percentage of actors, set a percentage (e.g. 10%)

Now approximately 10% of actors (based on flipper_id hashing) will have the feature enabled.

Usage in code stays the same:

if Flipper.enabled?(:new_dashboard, current_user)
  # user may or may not be in the rollout bucket
end

You can increase the percentage over time (e.g., 10% → 25% → 50% → 100%) as confidence grows.


Quick Reference

Check flag with user:

Flipper.enabled?(:feature_key, current_user)

Enable for everyone:

Flipper[:feature_key].enable

Disable for everyone:

Flipper[:feature_key].disable

Enable for specific user:

Flipper[:feature_key].enable(user)

Enable for org:

Flipper[:feature_key].enable(org)

Enable for group:

Flipper[:feature_key].enable_group(:admins)

Set percentage rollout:

Flipper[:feature_key].enable_percentage_of_actors(25) # 25%

Clone this wiki locally