Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Flags Tutorial #438

Merged
merged 9 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contents/docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ We maintain [a list of good first issues](https://github.com/PostHog/posthog/iss

Outside of tickets, if there are small improvements to layout, text, or functionality, feel free to raise a PR directly.

Alternatively, you can also [update PostHog's documentation](/../updating-documentation). To do so, take a look at our [Styleguide](https://github.com/PostHog/posthog.com/blob/master/STYLEGUIDE.md) before getting started.
Alternatively, you can also [update PostHog's documentation](/docs/updating-documentation). To do so, take a look at our [Styleguide](https://github.com/PostHog/posthog.com/blob/master/STYLEGUIDE.md) before getting started.

If you're planning to work on a bigger feature that is not on the list of issues, please raise an issue first so we can check whether that feature makes sense for PostHog as a whole.

Expand Down
2 changes: 1 addition & 1 deletion contents/docs/integrations/js-integration.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: JS Integration
title: JavaScript Integration
sidebar: Docs
showTitle: true
---
Expand Down
16 changes: 16 additions & 0 deletions contents/docs/tutorials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Tutorials
sidebar: Docs
showTitle: true
---

<br>

Welcome to our Tutorials section. Here you will find step-by-step tutorials about how to use PostHog and its features.

This is a new section of our Docs and we appreciate any suggestions you may have about what we should write next. To suggest a tutorial or contribute one yourself, feel free to open an issue or Pull Request on [GitHub under our posthog.com repo](https://github.com/PostHog/posthog.com).
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved


## **In This Section:**

- [Example](https://posthog.com)
206 changes: 206 additions & 0 deletions contents/docs/tutorials/feature-flags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
---
title: How to Safely Roll Out New Features
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved
sidebar: Docs
showTitle: true
---
<br />

<small class="note-block centered">_Estimated Reading Time: 8 minutes ☕☕_</small>

<br />


![](../../images/tutorials/banners/feature-flags.png)

<br />

Rolling out new features in your product can really be a pain.

As a company that is growing fast and [consistently putting out new functionality](/blog/we-ship-whenever), we know this very well.

You might have great tests and robust CI/CD workflows in place, but there's always the chance that something will go wrong, or that your users may not appreciate the change.

To make this process less painful and safer, you can use feature flags.

Feature flags allow you to safely deploy and roll back new features. It means you can deploy features and then slowly roll them out to your users. If something has gone wrong, you can roll back new features without having to re-deploy your application.

This tutorial will walk you through creating and using a feature flag with PostHog, cover some basic use cases, and answer some of the questions you may have when using them.

<span class='centered'>...</span>

_Prefer to watch a video? Check out the [Feature Flags section of our demo video](https://youtu.be/aUILrrrlu50?t=950) for a shorter overview of this functionality._

## Creating Feature Flags

yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved
### Step 1: Navigate to 'Experiments'

To find the feature flags page, click on 'Experiments' on the left sidebar in PostHog.

![Feature Flags Page](../../images/tutorials/feature-flags/feature-flags-page.png)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These images are hard to see without clicking into them because the page width is narrow. The consistency however (the whole screen each time) does make them look a lot nicer.

Could we expand the width a little?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will take a look

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only make them marginally larger - to make them significantly bigger would actually require some deeper tweaks


### Step 2: Creating a New Flag

While on the 'Experiments' page, click on the blue '+ New Feature Flag' button. This will open up a menu on the right side of the page, like so:

![Create Feature Flag](../../images/tutorials/feature-flags/create-flag.png)

### Step 3: Configuring Your Flag

With the menu open, you will see there are a few options you can configure for your flag. Here's the purpose of each one:

**Name**

A memorable name for you and your team to refer to the flag.

**Key**

Used to refer to your flag in your codebase. While the flag name does not affect the implementation, the key does. When adding the feature flag to your code, you will always use the key, never the name. In addition, changing a flag key may [affect the persistence of your flag](/docs/features/feature-flags#feature-flag-persistence).

<div class='note-block'><b>Pro tip:</b> Make sure you choose a key for your flag that is descriptive and styled consistently with your codebase. Changing a flag key will require you to update your codebase and may harm persistence, so it's best to avoid doing so.</div><br />

**Active**

This toggle is an important part of feature flags. It means you can turn feature flags on only when you're ready to do so, or off if something goes wrong. It can be used as a "kill switch" for features.

**Filter by user properties**
jamesefhawkins marked this conversation as resolved.
Show resolved Hide resolved

Feature flags can be rolled out based on a wide variety of filters. These are:

1. User properties
1. Cohorts
1. Percentage of users
1. A combination of the above

Under 'Filter by user properties', you can specify various properties and/or cohorts that a user must match in order to have the flag active. This works on an `AND` basis, meaning that a user must match all of the specified filters.

These filters are very powerful, allowing you to both offer a tailored UX to your users, as well as gather powerful insights into how different groups of user might behave. For example, you could define logic such as:

* Show technical content to users who have the `has_read_docs` property equal to `true`
* Roll out the new design only to users in the 'Dark Mode Users' cohort
* Show advanced options by default to users in the 'Organization Admins' cohort who have `@bigcompany.com` in their `email` property

**Roll out to a percentage of users**

This option can be used either by itself or in combination with the property/cohort filters.

When used by itself, it means that `X%` of your users will have the flag on and the other `(100-X)%` will have it off.

This mechanism is _random but deterministic_. What this means is that it is a weighted random selection that establishes which users will have the flag on or off, but a given flag _will persist_ for a every user (if nothing else changes). This ensures that users don't have a different experience each time they visit your app.

When used in conjunction with property filters, PostHog will first check if the user matches all the filters, and then apply the rollout percentage. This means that `X%` of the users who match the filters will see the flag, rather than `X%` of overall users.


<div class='note-block'><b>Technical Note:</b> Our rollout percentage mechanism works by hashing the distinct ID of a user with the flag key, casting it to an integer, and dividing it by 100. That gives us a number between 0 and 1 which we compare to the rollout percentage value (also between 0 and 1) to determine if a user should have the flag on or off. This ensures an acceptable degree of randomness and accuracy while allowing flags to persist.</div>


### Step 4: Saving Your Flag

Just click 'Save feature flag' and that's it! Your flag will now be active. Clicking on it will also allow you to edit it as you wish.

## Implementing the Feature Flag

When you create a feature flag, PostHog displays an example snippet that you can plug into your codebase. It looks something like this:

```js
if (posthog.isFeatureEnabled('new-beta-feature')) {
// do something
}
```

This snippet refers to our [JavaScript Integration](/docs/integrations/js-integration), which is also what we will be using for this tutorial. However, you can also use feature flags via our [API](/docs/api/overview) as well as other libraries, such as our [Python Integration](/docs/integrations/python-integration) (we're working to add this functionality to as many of our libraries as possible).

With that snippet, you can then do whatever you wish inside of it. You might change the CSS of a button, hide an entire section, or move things around. A simple example implementation would be:

```js
// Header text is blue by default
// If flag is on, make the text red
if (posthog.isFeatureEnabled('red-header-text')) {
document.getElementById('header-text').style['color'] = 'red'
}
```

While this is a trivial example, you can have as much logic as you want being powered by the feature flag. You can also combine flags with `OR` & `AND` operations to create more complex logic.

## Advanced Controls

### Loading Flags
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved

Every time a user loads a page we send a request in the background to an endpoint to get the feature flags that apply to that user. We store those flags as a cookie.

This means that for most page views the feature flags will be available immediately, *except* for the very first time a user visits your site.

To combat that, there's a callback you can use to wait for the flags to come in:

```js
posthog.onFeatureFlags(function() {
// feature flags are guaranteed to be available at this point
if (posthog.isFeatureEnabled('new-beta-feature')) {
// do something
}
})
```

In our JS Integration, the reason we store flags as a cookie is to reduce the load on the server and improve the performance of your app, as it doesn't need to always make an HTTP request, it can simply refer to data stored locally in the browser.

While this makes your app faster, it means that if your user does something mid-session which causes the flag to turn on for them, this will not be immediately updated. As such, if you expect your app to have scenarios like this _and_ you want flags to update mid-session, you can reload them yourself, by using the `reloadFeatureFlags` function.

```js
posthog.reloadFeatureFlags()
```

Calling this function will force PostHog to hit the endpoint for the updated information, and allows you ensure changes are reflected mid-session.

## Feature Flag Uses
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved

Feature flags are a very powerful piece of functionality that can be used in a wide variety of ways. How you use them will depend on your particular painpoints and internal best practices.

For us, here are some suggestions of use cases that could fit nicely with feature flags:

### A/B Testing

![A/B Testing Example](../../images/tutorials/feature-flags/ab-testing.png)
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved

<br />

In simple terms, A/B testing is a method for determining how to provide the best user experience or meet other product goals by testing how different features perform.

This could be used to answer questions such as "Do users click a button more often if it is blue or red?" or more complex questions like "How much more time do active users who have signed up for a free trial spend on our blog pages if we add a banner image?".

At PostHog, we're still working to provide built-in specific A/B Testing functionality. However, with feature flags, there's already a lot you can do in this regard.
yakkomajuri marked this conversation as resolved.
Show resolved Hide resolved

A great way to do this is by using [Cohorts](/docs/features/cohorts). If you filter your flags by cohort, you can then easily see the differences in behavior across different cohorts.

Here's an example view of Trends in PostHog filtering pageview events that contain the term "blog" in the URL, showing a breakdown between Cohort A (Beta Feature On) and Cohort B (Beta Feature Off):

![Trends A/B Testing](../../images/tutorials/feature-flags/trends-ab.png)

### Gradual Rollouts

There are many occasions when you might want to roll out a feature to your users slowly. Maybe you only want to enable it for Beta users, or you simply want to give users a transtion period.

Whatever the case may be, feature flags let you easily roll out features in an incremental way, increasing the portion of users that have the feature as fast or slow as you wish.

### "Master Toggles"

If you have to ship a big piece of functionality, chances are that you'll be doing it across multiple PRs.

As such, rather than attempt to coordinate a merge spree to ensure everything is live at once, you can create a feature flag that wraps all the new logic in all the pull requests. Then, once everything is merged and ready to go, you can simply flip the switch to release it.

Better yet, you can then release it slowly to make sure nothing breaks, and, if it does, you can easily turn it off with one click.

And this brings us to the next example.

### Kill Switches

You don't need feature flags _per se_ to implement kill switches, but having the ability to immediately turn a flag off is a nice add-on to the functionality.

Perhaps your goal all along was to do A/B testing for your UX, but, when something breaks, you can always roll it back safely with minor consequences (if implemented correctly).






## Example Code & Playground

Coming soon.
2 changes: 1 addition & 1 deletion contents/handbook/growth/posthog-array.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ If there are any new integration libraries - these won't appear above (since the
* Now it's time to push the branch to GitHub. Run ```git push --set-upstream origin posthog_array_VERSION```.
* Go to GitHub and create a pull request to merge the branch you just made with master. Request James Hawkins as the reviewer.

Refer to more information on [updating our documentation](../updating-documentation), if you are wondering how to use images correctly.
Refer to more information on [updating our documentation](/docs/updating-documentation), if you are wondering how to use images correctly.

### Content

Expand Down
2 changes: 1 addition & 1 deletion contents/handbook/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ The reason for making this transparent is to improve our communication, one of o

Anyone can submit a pull request to suggest updates or enhancements to this handbook through the [PostHog.com repo](https://github.com/posthog/posthog.com).

We treat this handbook as part of our Docs. Learn how to [update them](/updating-documentation).
We treat this handbook as part of our Docs. Learn how to [update them](/docs/updating-documentation).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/components/Layout/Layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,16 @@ code {
background-color: 'white';
}

.right {
display: block;
text-align: right;
}

.left {
display: block;
text-align: left;
}

@media screen and (max-width: 1076px) {
.docsHeader {
background-color: #f9f9f9;
Expand Down
Loading