Feature Flag approach with GraphQL and React 🕹
Tags: graphql, react, featureflag, apollo
Published: 2020-05-25 03:51:35

---
title: Feature Flag approach with GraphQL and React 🕹
published: true
description: Initial take when thinking about feature flags with GraphQL, React and Apollo.
tags: graphql, react, feature-flag, apollo
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/r5duhec8vytdp36yesnp.jpg
---

[Feature flag](https://martinfowler.com/articles/feature-toggles.html) (or feature toggle, feature switch…) comes with different shapes and implementations, however, is a well known and powerful technique for allowing teams to modify system behaviour without changing code.

The idea is to be able to enable or disable features during execution time without any deploy. That is a powerful tool with [various](https://github.com/search?q=feature+flag) implementations across different languages, the applications are many: A/B testing, toggle app configuration, delivery new features gradually, etc.

## Storage

While having feature flags is very handy they introduce complexity starting by the management of the flags. That is one of the reasons why you will find managed services like Optimizely, Rollout, and others. In addition to the feature, they offer a lot more like analytics, and targeting.

It does not mean that you need a third-party app or integration to start using feature flags. In fact, every tool and approach should be considered depending on what do you need at the implementation moment.

You may opt-in for a managed service or manage your own feature flags in your own database as well.

## API

So once you have decided how to manage the flags we need to expose them in our GraphQL API. The objective is always to strive for making your schema self contained and easy to understand, ideally, it should not reflect the way it is stored in the database (although it can).

We want to expose the features available for some user, app or instance. A query that provides that information could look like the following:

```graphql
type Query {
  enabledFeatures: [Feature!]!
}

type Feature {
  name: String!
}
```

In the schema above, we are defining two important units in our domain, they are:

- `Feature` and `enabledFeatures`. `Feature` is a representation of the feature you want to switch on and off and it only contains a `name` at the moment.
- `enabledFeatures` is a query that returns an array of `Feature`.

We only return the features enabled so whoever is consuming the API does not need to know the entire set of features. The lack of some feature in the array means that the feature is not visible/available.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cx0atpkrgrcfy0ct1f9s.gif)

> Note: In the backend, you can identify the user through headers such as [Authorization](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Authorization) and filter features for that user. Or filter based in any other information in the request, for example, [User Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent).

You can see this schema being served live on this [API sandbox](https://codesandbox.io/s/graphql-feature-flag-7jxju). I'm using [Apollo Server](https://www.apollographql.com/docs/apollo-server/) in the example.
{% codesandbox graphql-feature-flag-7jxju %}

## Querying

Having the contract defined we are now able to fetch features. You can play around on the playground built in the sandbox example.

```graphql
query {
  enabledFeatures {
    name
  }
}
```

In the React application, I will be using [Apollo Client](https://www.apollographql.com/docs/react/) as I'm familiar with the API, but it does not matter the library you use. You can follow along with the implementation of this [client sandbox](https://codesandbox.io/s/feature-flag-client-graphql-4jwpk?file=/src/App.js).

A component that queries all the features would look like the following:

```jsx
const QUERY = gql`
  query {
    enabledFeatures {
      name
    }
  }
`;

function BasicQuery() {
  const { loading, error, data } = useQuery(QUERY);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :</p>;

  return (
    <div>
      <h2>List of features:</h2>
      <ul>
        {data.enabledFeatures.map(feature => (
          <li key={feature.name}>
            <p>{feature.name}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

Having that is a good start point, right know you already have a way to query all the features and you can make use of it to dynamically turn something on and off. So let's make that.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o1zqbedg9v2f0pp655z8.gif)

### useFeatureFlag

I want to guard a component so every time the user hit that part of the code we only render it if the feature is enabled. To avoid writing this logic over and over again I'm going to build a hook (previously I've used [render props](https://reactjs.org/docs/render-props.html), but you can also make it a [HOC](https://reactjs.org/docs/higher-order-components.html) component, you can work with whatever suits you prefer). The hook gets a feature name it checks if that is enabled and returns the status to the caller.

```js
function useFeature(name) {
  const { loading, error, data } = useQuery(QUERY);

  let feature = {
    loading,
    error,
  };

  if (!data) return feature;

  const enabled = data.enabledFeatures.some(feature => feature.name === name);
  feature.enabled = enabled;

  return feature;
}
```

That hook uses the same query we used before and it will return whether or not the passed `name` is present in the list of features, as well as loading and error state if you want to handle the intermediate states. We can now use it in any component to switch the render output depending on it.

```jsx
const Feature3 = () => {
  const name = 'feature3';
  const feature = useFeatureFlag(name);

  if (feature.loading || feature.enabled === undefined) {
    return <p>Loading {name}...</p>;
  }

  if (feature.error) return <p>Error :</p>;

  if (feature.enabled) {
    return <h2>{name} is enabled.</h2>;
  }

  return <h2>{name} is disabled.</h2>;
};
```

If we have only `feature1` and `feature2` enabled when querying `feature3` we should see the disabled message. Similarly, if we query `feature2` or `feature1` we should see the enabled message.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/l9jcsno980upknac2qqy.gif)

## Caching and better UX

Although our `useFeatureFlag` is enough to define if a feature is enabled, it queries `enabledFeatures` when the component is mounted. Depending on the application and the goal of your flag it can decrease the user experience because the user will have to wait for the query to finish.

Thankfully `Apollo Client` comes by default with an [in-memory cache implementation](https://www.google.com/search?client=opera&q=apollo+in+memory+cache&sourceid=opera&ie=UTF-8&oe=UTF-8)! Knowing that we deduce the `useFeatureFlag` will be slower only on its first execution. After that, the result will be cached. However, we can go further and cache it ahead of time.

We can implement a pretty similar component to the `BasicQuery` what would follow the same principles as `useFeatureFlag`, but it is not concerned about any specific feature. It is only worried about querying them and rendering the children.

```jsx
function FeatureFlags({ children }) {
  const { loading, error } = useQuery(QUERY);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :</p>;

  return <React.Fragment>{children}</React.Fragment>;
}
```

You may customize the way you render by ignoring the loading state or error, depending on your needs.

It works like context providers and you could indeed use the context API to create a provider to share its features and consume them with hooks. But this approach may be good enough as well.

`FeatureFlags` could be placed in the top of your component tree or would wrap a portion of your App that can be controlled by the feature flags.

```jsx
const App = () => (
  <ApolloProvider client={client}>
    <FeatureFlags>
      <div className="App">
        <h1>Hello Feature Flag</h1>
        <section>
          <BasicQuery />
        </section>
        <section>
          <Feature2 />
        </section>
        <section>
          <Feature3 />
        </section>
      </div>
    </FeatureFlags>
  </ApolloProvider>
);
```

This approach is not sophisticated, however already have some advantages like saving network calls being fired on every `useFeatureFlag`. Which also avoids the pending state in every guarded component. The trade-off here is to slow down the overall load in favour of the later dependants rendering way faster.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/cdufcl4vem9lnqcrrkas.gif)

The cache consistency can be a problem if we change the feature in the backend, but the user already cached the queries. For working around that you may extend the hook to receive a [fetch policy](https://www.apollographql.com/docs/react/api/react-hoc/#optionsfetchpolicy) option. Apollo allows you to configure the way you interact with the cache and you can opt-in for `network-only`, for example. Nevertheless, the in-memory cache only lives until the page is refreshed it might not be that critical depending on your use case.

## What is next?

That is my initial take when thinking about feature flags with GraphQL. The possibilities are many and as I wrote several times in this article it will depend on your use cases! So make it better work for you.

In my perception potential extensions would be:
- Adding options or variations as a field of `Feature`, then you can branch the feature implementation depending on its variation or properties (aka A/B testing).
- Making the components and hooks more generic accepting the query as props to them.
- Adding a new query, `featureEnabled` to query the `enabled` status by the `name` directly from the backend so you do not have to filter it in the client-side.

What is your take on feature flags? 😊🙌🏽

> _cover image by [Mikkel Bech on Unsplash](https://unsplash.com/photos/phkp6WdpnIc)_
> This post is a complete rewrite of [feature flag approach for react using apollo client](https://medium.com/open-graphql/feature-flag-approach-for-react-using-apollo-client-5bfbd99c6cbd). I felt it needed an update.