Minimize delivery risk with progressive release
Tags: devops, featureflag, dotnet, testing
Published: 2023-01-27 12:53:43


This article is mainly about using feature flags to enhance delivery stability and speed in a microservice-based SaaS platform. This article combined traffic routing and feature flags to realize "Testing in production" & "Progressive Delivery" to minimize the release risk.

## Introduction
### Microservice

Microservices - also known as microservice architecture - is an architectural style that structures an application as a collection of services that are: Independently deployable; Loosely coupled; Organized around business capabilities; Owned by a small team; Highly maintainable, and testable. Lots of software products have a microservice-based architecture. It's more or less a fashion. 

### Reduce release risk: Testing in Production & Progressive release

To mitigate release stress and reduce release risk, we can take two steps before releasing a new version/feature to the entire public/final audience: Testing in Production and Progressive Delivery.

`Testing in production (TIP)` is a software development practice in which new code changes are tested on live user traffic rather than in a staging environment. It is one of the testing practices found in continuous delivery.

`Progressive Release` offers an additional strategy to help mitigate the risk of unexpected issues affecting users. They help by making a release available only to a specific percentage of a snap’s user base. This percentage can be initially small, perhaps 10% or 20%, and increases as confidence in a release grows.


<img height=330 src="https://user-images.githubusercontent.com/68597908/215022146-6a47b774-002c-4f0b-9bc5-b7cf0d66df7a.png" />

### Solution - Traffic routing

One solution is using traffic routing to switch between the current and the new release progressively. It often uses a service mesh (App Mesh, Istio, Linkerd, Open Service Mesh) or an ingress controller (Contour, Gloo, NGINX, Skipper, Traefik) for traffic routing.

For example, we have a new version of the microservice "sentence emoji classification algorithm". We can use a traffic routing solution to deliver progressively from the old algorithm to the latest version. 

For example, the [flagger.app](https://docs.flagger.app/) is an excellent tool for implementing the solution.


<img height=360 src="https://user-images.githubusercontent.com/68597908/215022249-3ec44502-b89a-46fd-833a-cf41996efa0c.png" />

### Solution - Feature flags

`Feature flag` is a modern engineering technology that decouples code deployments from feature releases, giving you control over who sees each feature and when they see it. 

With feature flags, you can progressively release or roll back individual features to or from a specific group of users without redeployment. You can toggle a feature on and off to subsets of users.

![image](https://user-images.githubusercontent.com/68597908/215022320-4405d356-237c-4a21-b58b-7f68df10e3cf.png)

There are several platforms for feature flag management, such as Launchdarkly, Unleash, FeatBit, etc. In this article, I will use FeatBit as a demo tool in a real-world example because only FeatBit's open-source version supports all I need in the demonstration.

### Combined solution

<img height=300 src="https://user-images.githubusercontent.com/68597908/215022422-6aceeb4d-e726-450b-a1a0-4ed41ae31783.png" />

The above table listed the main difference between traffic split & feature flags.

In many companies, both solutions are adopted to minimize the release risk. They combined two solutions to reduce the release risk. Here are the steps to deliver the new version and features progressively:

1. Deploy new version services with new containers.
2. Turn off feature flags of new features deployed on the new containers.
3. Use route traffic routing solution to deploy the new version in production progressively.
4. Turn on new features individually.
5. Testing features individually in production.
6. Progressive releases new features individually.

**Steps 1-3** prevent you from delivering an unexecutable version. **Steps 4-6** prevent you from delivering a new feature with a negative effect. **Steps 4-6** also prevent you from rolling back the entire new version if only one of the new features encounters the problem (especially when only a small group of users are impacted).

## Real-world example

I will use a housekeeping service platform to demonstrate how to implement feature flags to reduce release risk.

### Introduction of Housekeeping service platform

The housekeeping service platform (HKSP) is an open-source project developed by a cloud provider developer community. HKSP is a Shopify-like platform for housekeeper services. Housekeeper companies can register on the platform and build their housekeeper "online shop" (which can have its domain name).

![image](https://user-images.githubusercontent.com/68597908/215023253-256835fa-02ab-4d26-88c4-dcceab1c5390.png)

### Scenario and context

HKOSS has developed a new version which includes some bug fixes, new features, and UI/UX enhancement. The notification module is one of the new features requested by VanveHKC (one of the HKOSS team's customers). They want to deliver this feature to this customer without the risk that it might impact the customer's end-users.
The new version has changed something:

- Housekeeping staff office and customer center have been updated for feature "notification" and other new features.
- The message service has been added for the "notification module" feature. 
- The publish service has been updated for feature "notification" and other new features. The message center needs to call the service provided by the new version of publish service.
- There're also other changes related to other features. I won't describe here.

### Problem to resolve

1. Different new features are delivered to different housekeeping company tenants. The "Notification module" feature will be delivered to the company "VanvesHSK"; other features will be delivered to other companies.
2. If one feature encounters a bug, it shouldn't impact the delivery of other features.

### Strategy of delivery

- **Step-1**. Use feature flags to wrap up new features and turn off new features for all users.
- **Step-2**. Build new versions and deploy the new version online.
- **Step-3**. Use traffic routing solutions to progressively transfer the traffic from the old version to the new version. This prevents the new version containers from breaking the existing services.
- **Step-4**. Turn on the feature flag for the notification module, and let only the QA team and beta users access this feature. Test it in production.
- **Step-5**. Use a feature flag to deliver the "notification module" to end-users of VanveHKC progressively.

If we see it in detail, there are several solutions we can adopt based on the situation. For the "notification module", I proposed the solution below:

- Add a feature flag for notification on the web app project. Use traffic routing to switch between the old and the new version progressively.
- No feature flag on the message service project. Because it's a new independent service.
- No feature flag on the publish service project because it's a new independent interface. Use traffic routing to switch between the old and the latest version progressively.

![image](https://user-images.githubusercontent.com/68597908/215057128-d56040bf-e5de-4fc4-adc0-8817696be9ca.png)

### Step 1 - Use feature flags to wrap up new features.

#### 1.1 Build your feature flag environment

You can learn how to build the system through FeatBit's GitHub page. (https://github.com/featbit/featbit)[https://github.com/featbit/featbit]


<img height=400 src="https://user-images.githubusercontent.com/68597908/215057371-44fccadb-fe0f-41e2-a0f2-d107e595afc3.png" />

#### 1.2 Connect a feature flag SDK to projects

We need to use a feature flag to control the notification feature. We need to install the feature flag SDK to your project. 
Here we demonstrate how to install the feature flag SDK in a front-end application. Run command:

```
npm install featbit-js-client-sdk
```

Then we need to initiate SDK with users' basic information. Here is a screen capture of what it looks like.

1. Secret, a key to connect to the remote feature flag server.
2. API URL, the address of the remote feature flag server.
3. Configurable user information you will use to roll out features.


<img height=330 src="https://user-images.githubusercontent.com/68597908/215057853-e80daa4e-75a8-4779-8364-80892269e8fb.png" />

> ⚠️ I won't show detail here because this isn't a tutorial on how to use FeatBit. If you're interested in FeatBit, you can visit [its GitHub page](https://github.com/featbit/featbit) for more information. FeatBit provides various SDKs for javascript, java, c#, python, go, etc.


#### 1.3 Use the feature flag to wrap up and control the feature code.

In the web app project, find the code which runs the "notification module", and use a feature flag to wrap up the related code. Image below shows an example:

<img height=399 src="https://user-images.githubusercontent.com/68597908/215058751-6de4c81b-60a3-4f88-a48a-3702091b0430.png" />

The front-end app is written with VUE (a framework of javascript/typescript). If the flag code `featureStore.flags['notification']` execute and returns `true`, the "notification module" runs and is displayed in the front end APP. The "notification module" won't be executed if it returns `false`.

#### 1.4 Turn off the feature flag.

Before step 4 of the strategy, the new feature "notification module" shouldn't be delivered to users when the new version is deployed to production. We need to configure it on the feature flag management platform. As shown in the image below, the feature flag "notification" is turned off, and will return a value `false`.

<img src="https://user-images.githubusercontent.com/68597908/215059431-3a644e64-02df-4fbb-b12c-cce7320d878f.png" />

### Step 2 - Build a new version and deploy it to the microservice system.

In this demonstration, we must rebuild `front-end app` projects, `message service`, `publish service`, etc. We then deploy the new version to separate containers on the microservice system.

Many Cloud solutions, DevOps tools, and microservice frameworks help us to implement this operation. Most of the methods I used before were registering the Dockerized APP/service images to an online register, then pushing the image to an online container service (like Azure web app, AWS ECS, K8s, etc.).

I won't describe more about it in this post. 

### Step 3 - Use traffic routing to deploy the new version progressively.

Once you deploy the new version to the microservice system, you need a framework to manage the traffic so you can switch the traffic routing from the old version to the new version.

You can use a service mesh (App Mesh, Istio, Linkerd, Open Service Mesh) or an ingress controller (Contour, Gloo, NGINX, Skipper, Traefik) to achieve the goal. It depends on the microservices architecture. Many Clouds also provide a traffic routing for microservice. 

You can try the [Istio](https://istio.io/latest/about/service-mesh/)/[flagger.app](flagger.app) combined solution for practice. I won't describe more about it in this post. 

### Step 4 - Testing in production

Do you remember the code we wrote in step 1? We need to configure the portal UI to control who sees the feature and when they see it. (user sees the feature only if the flag returns true).

<img height=200 src="https://user-images.githubusercontent.com/68597908/215071906-9c005af5-dc39-4592-9de3-49a356fd2eda.png" />

Turn on the feature flag for the notification module, and let only the QA team and beta users see (access) this feature. Test it in production.

- If the user is in the QA group or is one of the beta users for the "notification module"，`featureStore.flags['notification']` should return `true`.
- If not, `featureStore.flags['notification']` return `false`

4.1 In the Segment page of FeatBit, create a new segment QA team, input the QA members into the "Including users" list in the "Targeting users" tab, then click Review and save。

![image](https://user-images.githubusercontent.com/68597908/215072224-e983e071-9c46-40fd-9750-53ee0ad3736f.png)

4.2 On the feature flag list page, choose the "Notification" flag and go to its Targeting page.

- a. Create a customized "Targeting rule": If the user belongs to the QA segment, then the feature flag `featureStore.flags['notification']` returns `true`; otherwise returns `false`.
- b. You can add beta users directly to the true value list in the Individual targeting tab. If the user belongs to this list, `featureStore.flags['notification']` returns `true`; otherwise returns `false`.
  
![image](https://user-images.githubusercontent.com/68597908/215072415-b93bc889-24cb-4322-9379-e7d022570a01.png)

4.3 Complete the setting and save it. Below are demonstrations in the video:

https://user-images.githubusercontent.com/68597908/215072970-665de9c1-ac29-4c49-8f41-4e6e8f76af5b.mp4

https://user-images.githubusercontent.com/68597908/215073000-2c142d3f-ed71-4cf9-b946-e452edd28e0c.mp4


> ⚠️ You can check FeatBit's official open-source repo to get more information on how to use  https://github.com/featbit/featbit

### Step 5 - Deliver the "notification module" to one HKC progressively.

It's easy to progressively release the "notification module" feature to users. You can change the default rule to `serve: Rollout percentage`, then input the percentage of all users who receive a true value. As shown below, we roll out the feature to 10% of users.

![image](https://user-images.githubusercontent.com/68597908/215073231-2b5d5bed-e989-4643-b57f-f3579fbbd11c.png)

#### 5.1 Progressive release in a single tenant

But in this scenario, we won't release the "notification module" to all end-users progressively because we want to only deliver the new feature to the business customer (a housekeeping service company (HKC )) who requested the feature. 

![image](https://user-images.githubusercontent.com/68597908/215079994-a1416a49-08cb-4f20-94d3-a681be6cc08a.png)

So we need to create a rule that only users under `sho.saas-housekeeper.chouldbu` domain can see the "notification module". To release the feature progressively, we need to configure the rule to `serve: Rollout percentage`. As shown below, the "notification module" has been delivered progressively only to users under the domain `sho.saas-housekeeper.chouldbu`.

![image](https://user-images.githubusercontent.com/68597908/215080167-27afbacc-ae6b-435e-aa6d-ebfb112e2613.png)


### 5.2 Progressive release by a custom attribute

Service staff in a Housekeeping Company can be organized/grouped by small region (for example, a street). I call it a regional team. The staff users in the same regional team should have the same feature. If we roll out the feature by `userKey`, members in one team will struggle in teamwork.

So instead of a percentage rollout identified by `userKey`, I can use a customized attribute as a rollout key. In this scenario, I use `team-region` as the rollout key.

![image](https://user-images.githubusercontent.com/68597908/215080349-629e144d-81a9-4f18-a033-9a00433a3262.png)

Now, service staff in the same regional team will have the same feature.

## Conclusion

Minimizing delivery risk is always critical for the teams who serve clients seriously. Combining traffic routing and feature flag solutions helps teams significantly reduce delivery risk.

In reality, this combined solution will also help you to ship new features faster. Because you're fearless in shipping new features, the risk is under control. This allows you significantly innovate faster and increase your business income.

To minimize the delivery risk, we still have a lot of work to do. I will try to write more articles about this topic.

I hope this article is helpful for you in practice. Leave your comment here or join our [GitHub repo(https://githuib.com/featbit/featbit)](https://githuib.com/featbit/featbit) to keep in contact. If you find this helpful article, please star us.

-----------------------------

Made by [FeatBit](https://www.featbit.co) @ 2023