Feature toggles can be used in both vets-api and vets-website to manage unreleased features. Use feature toggles to test out new functionality (applications, features, VA.gov content pages, Metalsmith) in the development, staging, or production environments for a set of users.

Feature toggles:

  • Allow for production toggle switching without redeploying vets-website

  • Provide a user interface for managing feature toggle behavior

  • Provide code helpers for handling common user experience scenarios

  • Are powered by an open-source gem called Flipper gem

Writing good feature toggles

Keep the following items in mind as you add feature toggles:

  • Remember that each environment has its own set of feature toggle values.

  • Test your feature toggle in staging before using it in production.

  • Remove feature toggles as soon as they are not needed.

  • Make toggles that are easy to delete by gating a behavior in as few places as possible. It's often better to have blocks of repeating code that can be quickly deleted later than it is to gate several small pieces of code.

After a page is rendered, the feature toggle client retrieves the latest toggle values from the feature toggle service and the page is updated using the latest feature toggle values. The application shows a loading state for the new feature while the toggle values are retrieved from the service.

Adding a new feature toggle (frontend)

Follow these steps to add and use a new feature toggle in vets-website.

1. Determine your feature toggle name

There are no naming conventions. Current examples put the application name first, such as facilityLocatorShowCommunityCaresand profileShowDirectDeposit.

2. Add the feature name to vets-api by updating config/features.yml

features:
 app_name_then_your_feature_name:
   actor_type: user
   description: >
     This describes what the feature does and
     which team is responsible for the toggle.
CODE

Be sure to use snake case for the feature name.

3. Determine how you want the feature toggle to be "sticky"

  • For the behavior to be consistent across all devices for a logged in user choose user as the actor_type.

  • For the behavior to be consistent for a user for the duration of a cookie within a single browser, regardless of their logged in status choose cookie_id as the actor_type.

4. Run vets-api locally

This can be done on main after your pull request (PR) is merged or off of your feature branch.

Navigate to http://localhost:3000/flipper/features and verify that you see your new feature name. If not, restart your rails server.

5. Add the feature toggle name to vets-website by updating featureFlagNames.js

const FEATURE_FLAG_NAMES = Object.freeze({
 showYourFeatureName: 'app_name_then_your_feature_name',
})
CODE

The key should be camelCase for use in JavaScript, but the value should exactly match the toggle name in features.yml.

6. Submit a PR for each feature

Cross-linking the PRs in a comment will make it easier for the reviewers to check.

7. Use the selector helper to build a selector for your feature toggle

In the following example, the toggleValues object is a flat list of toggleName and boolean key value pairs. Also, note that toggleValues is imported from platform/site-wide/feature-toggles/selectorsand FEATURE_FLAG_NAMES is imported from platform/utilities/feature-toggles/featureFlagNames.

To learn more about selectors, see this article: Redux Selectors: A Quick Tutorial

// import the toggleValues helper
import { toggleValues } from 'platform/site-wide/feature-toggles/selectors';

// use the toggleValues helper to select the toggle values list
export const appNameThenYourFeatureName = state =>
  toggleValues(state).appNameThenYourFeatureName;
CODE

Here is a live eSee an example from vets-website.

8. Use the feature toggle value to gate your new behavior

For example, you can use the selector above in mapStateToPropsto pass the toggle as a prop into your component.

Currently, the feature toggle values are only available on the global redux state.

function mapStateToProps(state) {
  return {
    showYourFeatureName:
      appNameThenYourFeatureName(state),
  };
}

...
// inside your connected component

render() {
   const { showYourFeatureName } = this.props;

   return (
     { showYourFeatureName && <NewFeature /> }
   );
}
CODE

9. Use the Flipper UI to test out the toggle locally

Refresh the page to update the feature toggle state. This value can take up to a minute to update in staging and production.

Adding a new feature toggle (backend)

To add and use a new feature toggle in vets-api, follow these steps.

1. Determine your feature toggle name

There are no naming conventions. Current examples put the application name first, such as facilityLocatorShowCommunityCaresand profileShowDirectDeposit.

2. Add the feature name to vets-api by updating config/features.yml

features:
   app_name_then_your_feature_name:
   actor_type: user
   description: >
     This describes what the feature does and
     which team is responsible for the toggle.
CODE

Be sure to use snake case for the feature name.

3. Determine how you want the feature toggle to be "sticky"

  • For the behavior to be consistent across all devices for a logged in user choose user as the actor_type.

  • For the behavior to be consistent for a user for the duration of a cookie within a single browser, regardless of their logged in status choose cookie_id as the actor_type.

4. Run vets-api locally

This can be done on master after your pull request (PR) is merged or off of your feature branch.

Navigate to http://localhost:3000/flipper/features and verify that you see your new feature name. If not, restart your rails server.

Backend example

def base_method_name(params)
  if Flipper.enabled?(:feature_flag, @current_user)
    base_method_name_feature_enabled(params)
  else
    base_method_name_feature_disabled(params)
  end
end
def base_method_name_feature_enabled(params)
  # How it behaves with the feature toggle enabled
end
def base_method_name_feature_disabled(params)
  # How it behaves without the feature toggle enabled
end

### spec
RSpec.describe Object do
  context "Feature feature_flag=true" do
    before do
      Flipper.enable(:feature_flag)
    end
    it "behaves this way with the feature enabled" do
    end
  end
  context "Feature feature_flag=false" do
    before do
      Flipper.disable(:feature_flag)
    end
    it "behaves this way with the feature disabled" do
    end
  end
end
CODE

Enabling and disabling features using the Flipper UI

1. Access Flipper UI

You can enable or disable features in the Flipper UI. The following environments have a Flipper UI available.

To access the Flipper UI, you must sign in using an identity-verified id.me user that is listed in settings.yml:

flipper:
  admin_user_emails:
    - email@email.us
    - email1@email.us
CODE

If you are not on the list, you can add yourself or your teammates to the file. - If you're not sure if your account is identity-verified, you can check by going to the VA.gov Sign in page. If you need to verify your account you'll see a Verify with ID.me button.

2. Configure Flipper UI settings

Once you have logged into the Flipper UI, you can define configuration settings to determine who can see your new feature.

The values of each toggle are cached in memory for one minute, so it may take that long to see the effect of enabling or disabling the toggle.

Configuration option

Use case

Enable/Disable for everyone

Enable or disable the feature for all users.

Percentage of Logged in Users

Enable the feature for only a percentage of logged in users. It will be applied to the same users each time they return to the site (even when they log out and back in) as long as you don't change the percentage.

If the feature toggle's actor_type in config/features.yml is set to cookie_id rather than user, the feature instead applies to only a percentage of users for the duration of a cookie within a single browser, regardless of their logged in status. This is useful when you need to apply a staged rollout that involves an unauthenticated user experience.

Percentage of Time

Enable a feature for all users for a percentage of time.

Register a Group

Enable a feature for a group of registered users.

Add indivudual email address to Users section

Enable a feature for a select few users.

For performance reasons, the list of users is intended to be small — do not use this option for hundreds of users.

Example screenshot of Flipper UI:

Flipper UI for defining feature toggle configurations.