# ConfigCat Docs
> Learn more on how to use ConfigCat Feature Flags.
## Getting Started
### Getting Started
Copy page
This page is an overview and a short guide on how to get started.
**ConfigCat** is a cloud-based service that lets you release features without code deployments.
You can use it with many similar techniques, such as feature flags/toggles, canary releases, soft launches, A-B testing, remote configuration management, and phased rollouts. Configure your application and features even after deployment.
#### The birth of a Feature Flag[](#the-birth-of-a-feature-flag "Direct link to The birth of a Feature Flag")
First, **add a feature flag** on the *ConfigCat Dashboard*, and then you can **connect your application** to the ConfigCat service to access your feature flag.
##### Create a feature flag on the *ConfigCat Dashboard*[](#create-a-feature-flag-on-the-configcat-dashboard "Direct link to create-a-feature-flag-on-the-configcat-dashboard")
1. [Log in](https://app.configcat.com) to the *Dashboard*
2. Click *ADD FEATURE FLAG* and give it a name.

##### Explore with Our Tutorial App[](#explore-with-our-tutorial-app "Direct link to Explore with Our Tutorial App")
Before diving into connecting your actual application, consider exploring our [Feature Flags Tutorial](https://tutorial.configcat.com/?lm=11). This interactive app provides a practical and engaging way to learn about ConfigCat and feature flags without needing to integrate immediately with your current projects. It's perfect for beginners to understand the functionalities and advantages of using feature flags effectively.

[Start the Feature Flags Tutorial](https://tutorial.configcat.com/?lm=12)
##### Connect your application[](#connect-your-application "Direct link to Connect your application")
There are ready-to-use code snippets for `Browser (JavaScript)`, `Angular`, `React`, `Node.js`, `Deno`, `Bun`, `Cloudflare Worker`, `.NET (C#)`, `Java`, `Go`, `PHP`, `Python`, `Android (Java)`, `iOS (Swift)`, `Dart / Flutter`, `Kotlin Multiplatform`, `Ruby`, `Elixir`, `C++`, `Rust`, `Unreal Engine` on the [ConfigCat Dashboard](https://app.configcat.com), just scroll down to the **SDK Key and steps to connect your application** section.
All the ConfigCat SDKs are open-source and available on [GitHub](https://github.com/configcat).
See the detailed [Docs on how to use the ConfigCat SDKs.](https://configcat.com/docs/sdk-reference/overview.md)
Here's a short example to demonstrate the concept:
```js
// 0. If necessary, install the ConfigCat SDK package for the platform you use.
// E.g. `npm install @configcat/sdk`
// 1. Import the ConfigCat SDK package.
import * as configcat from '@configcat/sdk';
// 2. Get a client object for the SDK Key of your config.
const client = configcat.getClient('#YOUR-SDK-KEY#');
// 3. Evaluate a feature flag using the client object.
const value = await client.getValueAsync('isMyFeatureEnabled', false);
// 4. Based on the value of the feature flag decide whether or not to enable the related feature.
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
---
## Main Concepts
### Main Concepts
Copy page
#### Feature Flag or Setting[](#feature-flag-or-setting "Direct link to Feature Flag or Setting")
A *Setting* is an essential bit of *ConfigCat*. It can be of multiple types, such as an on/off switch (bool), number (int, double) or any text (string). You can use it to change your application's behavior remotely, without a new deployment.
A *Feature Flag* is a *Setting* of type Bool.
##### Anatomy of a *Feature Flag* or *Setting*[](#anatomy-of-a-feature-flag-or-setting "Direct link to anatomy-of-a-feature-flag-or-setting")
| Properties | Description |
| ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| Name | A human readable name that differentiates the *Setting* on the *ConfigCat Dashboard*. e.g., `My Cool Feature enabled`. |
| Key | A variable name within your code. e.g., `isCoolFeatureEnabled`. |
| Type | Type of information you'd like to keep in the *Setting*. e.g., On/Off Toggle, Text, Number |
| Value | The actual value of your *Setting*. e.g., `true`, `false`. Can be different in each environment. |
##### About *Setting* types[](#about-setting-types "Direct link to about-setting-types")
| Setting Kind | Setting Type | Description |
| -------------- | ------------ | --------------------------------------------------------------------------------- |
| On/Off Toggle | Boolean | true/false, usually referenced as Feature Flag, Feature Toggle or Feature switch. |
| Text | String | Any string, max. 100000 characters, can't be empty. |
| Whole Number | Integer | Any whole number within the range of `Int32`. |
| Decimal Number | Double | Any decimal number within the range of `double`. |
##### Free-form values vs predefined variations[](#free-form-values-vs-predefined-variations "Direct link to Free-form values vs predefined variations")
ConfigCat supports two value-modes for feature flags:
* **Free-form values**: Allows you to enter a feature flag's exact value each time you set it. Best for simple, one-off configurations or quick experiments.

* **Predefined Variations**: Allows you to define a set of reusable values upfront when creating a feature flag. These variations can then be selected from a dropdown when setting up flag rules. Choose this mode to ensure consistency across rules, prevent typos in complex values (like JSON configurations), and provide self-documenting configurations for your team.

tip
Learn more about [predefined variations](https://configcat.com/docs/advanced/predefined-variations.md), including when to use this value-mode, how to convert between the two value-modes, and best practices.
#### Config[](#config "Direct link to Config")
A *Config* is a collection of *Settings*. *Configs* help you organize settings around topics, or around your software components. A *Config* is like an online version of a traditional config file.
#### Environment[](#environment "Direct link to Environment")
An environment in ConfigCat represents an environment in your development lifecycle (like production, staging, development etc.). Different environments have the same settings but can have different values.
info
Each environment-config pair has its own SDK Key which must be used to initialize the ConfigCat SDK within your application.
#### Product[](#product "Direct link to Product")
A collection of *Configs*, *Environments* and *Team members*. A *Product* typically represents your application (or your service) and the people working on it. It might be a good idea to invite others to your *Product* to collaborate.
#### Organization[](#organization "Direct link to Organization")
An *Organization* represents a collection of preferences that are valid for all the *Products* and *Members* who belong to an *Organization*. Like billing information, authentication rules or data privacy preferences.
---
## Targeting
### Feature Flag Evaluation
Copy page
This document offers an in-depth explanation of how the SDK determines the value of a feature flag when executing the `GetValue` function. Understanding this process requires prior knowledge of [targeting concepts](https://configcat.com/docs/targeting/targeting-overview.md).
The feature flag's value is determined by:
* The feature flag's rules defined on the Dashboard,
* The [User Object](https://configcat.com/docs/targeting/user-object.md) provided to the `GetValue` function, and
* The [default value](https://configcat.com/docs/targeting/targeting-overview.md#default-value) passed to the `GetValue` function.
The feature flag's value always comes from exactly one rule, following this algorithm:
1. **Evaluation of Targeting Rules:** If Targeting Rules are present, the SDK evaluates them one by one, from top to bottom. It checks if all the conditions in the rule's IF part are met (i.e. all the conditions evaluate to true).
* If the conditions are met, the THEN part determines the value to return. However, if the THEN part contains Percentage Options but the [Percentage Evaluation Attribute](https://configcat.com/docs/targeting/percentage-options.md#percentage-evaluation-attribute) is missing from the User Object, the SDK will skip the Targeting Rule and continue with the next rule - even though the Targeting Rule's conditions are met.
* If the conditions aren't met, the SDK moves to the next Targeting Rule, or to step 2 (below) if there are no more Targeting Rules.
2. **Evaluation of Percentage Options:** If a Percentage Options rule exists, the SDK executes the [Evaluation of Percentage Options](#evaluation-of-percentage-options) algorithm to determine which Percentage Option applies to the user and returns the value associated with that option. If the [Percentage Evaluation Attribute](https://configcat.com/docs/targeting/percentage-options.md#percentage-evaluation-attribute) is missing from the User Object, the SDK skips to step 3 (below).
3. **Returning simple value:** At this stage, the only remaining "rule" is the simple value specified at the end of the feature flag, which the SDK then returns.
In the event of an unexpected error during evaluation, the SDK returns the [default value](https://configcat.com/docs/targeting/targeting-overview.md#default-value) passed to the `GetValue` function.
#### Evaluation of a Targeting Rule[](#evaluation-of-a-targeting-rule "Direct link to Evaluation of a Targeting Rule")
The SDK evaluates the conditions in the rule's IF part one by one, from top to bottom. The result of a condition can be one of the following: `true`, `false` or `cannot evaluate`.
The result `cannot evaluate` occurs when the necessary user attribute is missing, invalid or incorrectly formatted (the SDK logs these issues as warnings).
A Targeting Rule matches only when all its conditions evaluate to `true`. In any other cases, it doesn't match.
##### Evaluation of a User Condition[](#evaluation-of-a-user-condition "Direct link to Evaluation of a User Condition")
The SDK looks up the comparison attribute (the user attribute referenced by the condition) in the [User Object](https://configcat.com/docs/targeting/user-object.md). It compares the attribute value to the comparison value that is set on the Dashboard. The comparison is done according to the selected comparator, resulting in a `true` or `false` value. This will be the result of the condition.
The result of the condition will be `cannot evaluate` in case the comparison attribute is missing (`null`, `undefined`, `""`) or invalid (not of the type expected by the comparator or not formatted properly). In such cases, the Targeting Rule containing the condition will be skipped, and the evaluation will continue with the next rule.
##### Evaluation of a Flag Condition[](#evaluation-of-a-flag-condition "Direct link to Evaluation of a Flag Condition")
Using the same User Object used to evaluate the dependent flag, the SDK evaluates the prerequisite flag (the feature flag referenced by the condition). Then, the result is checked against the comparator. In case the prerequisite flag is not a boolean setting, the result is compared to the comparison value that is set on the Dashboard. The comparison results in a `true` or `false` value. This will be the result of the condition.
In case the prerequisite flag is missing or there is a type mismatch between the return value and the comparison value, the evaluation process stops, and the SDK will return the [default value](https://configcat.com/docs/targeting/targeting-overview.md#default-value). (Though this can happen only when using the [flag overrides](https://configcat.com/docs/sdk-reference/js/overview.md#flag-overrides) feature with invalid data.)
##### Evaluation of a Segment Condition[](#evaluation-of-a-segment-condition "Direct link to Evaluation of a Segment Condition")
The SDK looks up the segment referenced by the condition. Then evaluates the condition described by the segment similarly to [User Conditions](https://configcat.com/docs/targeting/targeting-rule/user-condition.md). Finally, the result is checked against the comparator:
* For **IS IN SEGMENT**, the result of the Segment Condition will be the same as the result of the segment itself.
* For **IS NOT IN SEGMENT**, the result will be negated (i.e. it will be the opposite of the result of the segment).
If the segment evaluates to `cannot evaluate`, so does the Segment Condition.
The evaluation process stops if the referenced segment is missing, and the SDK will return the [default value](https://configcat.com/docs/targeting/targeting-overview.md#default-value). (Though this can happen only when using the [flag overrides](https://configcat.com/docs/sdk-reference/js/overview.md#flag-overrides) feature with invalid data.)
#### Evaluation of Percentage Options[](#evaluation-of-percentage-options "Direct link to Evaluation of Percentage Options")
[Percentage Options](https://configcat.com/docs/targeting/percentage-options.md) are designed to be *consistent* and *sticky* across all SDKs, which means that users with the same attributes fall in the same group and get the same feature flag value across the supported platforms as long as the percentage split is the same.
The SDK looks up the [Percentage Evaluation Attribute](https://configcat.com/docs/targeting/percentage-options.md#percentage-evaluation-attribute) in the [User Object](https://configcat.com/docs/targeting/user-object.md), then:
* The SDK creates a hash from the combination of the specific feature flag's key and the Percentage Evaluation Attribute's value (by default, it is the user identifier).
* The hashing algorithm assigns the user a number between 0 and 99.
* The assigned number determines which group the user falls into, i.e. which Percentage Option applies to the user.
The fact that the above algorithm is implemented across all SDKs guarantees [stickiness](https://configcat.com/docs/targeting/percentage-options.md#stickiness), [consistency](https://configcat.com/docs/targeting/percentage-options.md#consistency) and [randomness](https://configcat.com/docs/targeting/percentage-options.md#randomness).
info
The evaluation process is entirely implemented within the SDKs, meaning your users' sensitive data never leaves your system. The data flow is one-way – from ConfigCat CDN servers to your SDKs – and ConfigCat does not receive or store any attributes of the [User Object](https://configcat.com/docs/targeting/user-object.md) passed to the SDKs. This design prioritizes the privacy and security of user data.
##### Example scenarios for Percentage Options[](#example-scenarios-for-percentage-options "Direct link to Example scenarios for Percentage Options")
The following scenarios show how Percentage Options enable controlled and gradual rollouts of features.
Let's imagine the following setup:
* you have two users: Jane and Joe,
* you have two features flags: **isTwitterSharingEnabled** and **isFacebookSharingEnabled**,
* the feature flags use percentage-based targeting,
* the Percentage Evaluation Attribute is the user identifier (which is simply the users' name in this example).
First, the users are assigned a number between 0 and 99 based on the hash of the feature flag's key and their identifier. According to the Percentage Options specified on the Dashboard, this number determines which group they are assigned to, i.e. whether or not the feature is enabled for them.
Let's assume the hash algorithm produces the following numbers:
| | isTwitterSharingEnabled | isFacebookSharingEnabled |
| ---- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| Jane | `hash('isTwitterSharingEnabled' + 'Jane') mod 100` results in **8** | `hash('isFacebookSharingEnabled' + 'Jane') mod 100` results in **64** |
| Joe | `hash('isTwitterSharingEnabled' + 'Joe') mod 100` results in **32** | `hash(isFacebookSharingEnabled' + 'Joe') mod 100` results in **12** |
1\. **Initial Setup: 0% ON / 100% OFF**
| | isTwitterSharingEnabled 0% ON / 100% OFF | isFacebookSharingEnabled 0% ON / 100% OFF |
| ---- | --------------------------------------------- | ---------------------------------------------- |
| Jane | 8 >= 0 → **OFF** | 64 >= 0 → **OFF** |
| Joe | 32 >= 0 → **OFF** | 12 >= 0 → **OFF** |
2\. **Adjustment to 10% ON / 90% OFF** In this case both feature flags are enabled for only 10% of users.
| | isTwitterSharingEnabled 10% ON / 90% OFF | isFacebookSharingEnabled 10% ON / 90% OFF |
| ---- | --------------------------------------------- | ---------------------------------------------- |
| Jane | 8 < 10 → **ON** | 64 >= 10 → **OFF** |
| Joe | 32 >= 10 → **OFF** | 12 >= 10 → **OFF** |
info
The **isTwitterSharingEnabled** feature flag is enabled only for Jane because Joe's user identifier places him in a different group.
However, **isFacebookSharingEnabled** is disabled for both of them even though both feature flags are set to 10% ON / 90% OFF. This happens because the feature flag key is also involved in computing the hash.
3\. **Increasing *isTwitterSharingEnabled* to 40% ON / 60% OFF**
| | isTwitterSharingEnabled 40% ON / 60% OFF | isFacebookSharingEnabled 10% ON / 90% OFF |
| ---- | --------------------------------------------- | ---------------------------------------------- |
| Jane | 8 < 40 → **ON** | 64 >= 10 → **OFF** |
| Joe | 32 < 40 → **ON** | 12 >= 10 → **OFF** |
4\. **Rolling Back to a Safer 10% ON / 90% OFF**
Same setup as in Step 2.
There are cases when you want to roll back a feature flag to a safer state. In this case, you can change the Percentage Options to 10% ON / 90% OFF again. The sticky nature of percentage-based targeting ensures that the same userbase is served **ON** as in Step 2, not another random 10% of users.
| | isTwitterSharingEnabled 10% ON / 90% OFF | isFacebookSharingEnabled 10% ON / 90% OFF |
| ---- | --------------------------------------------- | ---------------------------------------------- |
| Jane | 8 < 10 → **ON** | 64 >= 10 → **OFF** |
| Joe | 32 >= 10 → **OFF** | 12 >= 10 → **OFF** |
5\. **Final Step: Moving to 100% ON / 0% OFF**
After testing the feature flags, you can safely move them to 100% ON. This enables the features for all users.
| | isTwitterSharingEnabled 100% ON / 0% OFF | isFacebookSharingEnabled 100% ON / 0% OFF |
| ---- | --------------------------------------------- | ---------------------------------------------- |
| Jane | 8 < 100 → **ON** | 64 < 100 → **ON** |
| Joe | 32 < 100 → **ON** | 12 < 100 → **ON** |
---
### Percentage Options
Copy page
#### What are Percentage Options?[](#what-are-percentage-options "Direct link to What are Percentage Options?")
Using *Percentage Options*, you can define that a certain percentage of users should receive a specific value.
This way, you can gradually release a new feature to a subset of users. Instead of releasing a feature to all users simultaneously, a specific percentage of users are selected to receive access to the feature. This allows developers to control and monitor the impact of the new feature in a controlled manner.
#### How to add Percentage Options?[](#how-to-add-percentage-options "Direct link to How to add Percentage Options?")
You can add Percentage Options to a feature flag by clicking the **+%** button on the Dashboard.

#### How does it work? - Anatomy of Percentage Options[](#how-does-it-work---anatomy-of-percentage-options "Direct link to How does it work? - Anatomy of Percentage Options")
Percentage Options is a list of *% value* and *served value* pairs, where % values add up to 100.
It divides users into groups according to the percentage split defined by the % values. The grouping is random and based on the [Percentage Evaluation Attribute](#percentage-evaluation-attribute). By default, this is the [User Object's](https://configcat.com/docs/targeting/user-object.md) **Identifier** attribute. However, you can use any other user attribute as the basis of the grouping.
info
If the Percentage Evaluation Attribute is not present in the [User Object](https://configcat.com/docs/targeting/user-object.md), the ["To unidentified" value](https://configcat.com/docs/targeting/targeting-overview.md#to-all-users--to-all-other--to-unidentified-value) will be returned. (Read more about the feature flag evaluation algorithm [here](https://configcat.com/docs/targeting/feature-flag-evaluation.md).)
Percentage Options are designed to be [sticky](#stickiness) and [consistent](#consistency) across all SDKs, ensuring a reliable experience.
##### % value[](#-value "Direct link to % value")
Any number between 0 and 100 that represents a randomly allocated group of your users.
##### Served value[](#served-value "Direct link to Served value")
The value to return when the user falls into the group determined by the % value.
##### Number of Percentage Options[](#number-of-percentage-options "Direct link to Number of Percentage Options")
In the case of a feature flag (boolean setting), there must be two options. One for the **ON** and one for the **OFF** state.
In the case of a string, integer or double setting, the maximum number of options [depends on your subscription plan](https://configcat.com/docs/subscription-plan-limits.md). You can add options by clicking the **+% OPTION** button.
#### Percentage Options within Targeting Rules[](#percentage-options-within-targeting-rules "Direct link to Percentage Options within Targeting Rules")
Percentage Options can be used in combination with Targeting Rules.
In this case, the Percentage Options will be evaluated only if the Targeting Rule matches. In other words, the Percentage Options apply only to the users that matched the Targeting Rule.
info
If the Percentage Evaluation Attribute is not present in the [User Object](https://configcat.com/docs/targeting/user-object.md), the targeting rule will be skipped - despite the matching Targeting Rule. Read more about the feature flag evaluation algorithm [here](https://configcat.com/docs/targeting/feature-flag-evaluation.md).

#### Percentage Evaluation Attribute[](#percentage-evaluation-attribute "Direct link to Percentage Evaluation Attribute")
The *Percentage Evaluation Attribute* (sometimes called *percentage attribute*) is the user attribute by which users are grouped. By default, it is the [User Object's](https://configcat.com/docs/targeting/user-object.md) **Identifier** attribute. However, you can use any other user attribute as the basis of the grouping (see the example use case [below](#percentage-options-based-on-other-user-attributes)).
##### How to change the Percentage Evaluation Attribute?[](#how-to-change-the-percentage-evaluation-attribute "Direct link to How to change the Percentage Evaluation Attribute?")
In the top right corner of the feature flag, open the kebab (3 dots) menu and choose the **Change percentage attribute** item.
info
The selected Percentage Evaluation Attribute applies to all Percentage Options within the feature flag - but only in the current ConfigCat environment.

#### Stickiness[](#stickiness "Direct link to Stickiness")
*Stickiness* means that the same user will always get the same value for the same percentage split in the case of a specific feature flag, regardless of the history of the feature flag. This is achieved by implementing a deterministic hashing algorithm based on the feature flag's key and the Percentage Evaluation Attribute.
For example, if you have a feature flag with a Percentage Option of **20% ON**, then you change the Percentage Option to **40% ON**, and then back to **20% ON**, the same 20% of users will get the **ON** value for the feature flag just like the first time.
For a demonstration of this concept, see this [example scenario](https://configcat.com/docs/targeting/feature-flag-evaluation.md#example-scenarios-for-percentage-options).
#### Consistency[](#consistency "Direct link to Consistency")
*Consistency* means that the same user will always get the same value for the same percentage split in the case of a specific feature flag, no matter which SDK is used. This is achieved by using the same hashing algorithm across all SDKs.
For example, if you have a feature flag with a Percentage Option of **20% ON**, then the same 20% of users will get the **ON** value across all SDKs. No matter if a user is on iOS, Android, or Web, they will always get the same value for the feature flag.
#### Randomness[](#randomness "Direct link to Randomness")
The same user might get different values for the same percentage split in the case of different feature flags. This is because the hashing algorithm is based on the combination of the feature flag's key and the Percentage Evaluation Attribute. Since feature flag keys are unique, the resulting hashes will usually be different as well.
For example, if you have two feature flags with Percentage Options of **20% ON**, then a different 20% of users will get the **ON** value for each feature flag.
#### Examples[](#examples "Direct link to Examples")
##### Simple phased rollout / Canary release / Percentage rollout scenario[](#simple-phased-rollout--canary-release--percentage-rollout-scenario "Direct link to Simple phased rollout / Canary release / Percentage rollout scenario")
###### Context[](#context "Direct link to Context")
Our demo company, Whisker Co. is about to release a new feature called **Park Weather Info**. The stakeholders want to make sure that the new feature is received well by the customers.
###### Goal[](#goal "Direct link to Goal")
To get some feedback from our customers before releasing it to everyone, we initially want to make the feature available to 20% of the customers only.
###### Solution[](#solution "Direct link to Solution")
Let's create a feature flag called **Enable Park Weather Info** with Percentage Options set to **20% ON** and **80% OFF**.

##### A/B/n testing scenario[](#abn-testing-scenario "Direct link to A/B/n testing scenario")
###### Context[](#context-1 "Direct link to Context")
The marketing specialists at Whisker Co. want to introduce a discount strategy to boost webshop purchases. They have several ideas but lack the statistical data needed to determine which would be most effective.
###### Goal[](#goal-1 "Direct link to Goal")
To learn which is the most effective discount strategy, we want to perform an A/B/C test.
###### Solution[](#solution-1 "Direct link to Solution")
We need a string or integer setting for this task because we need to represent 3 different variations. Let's create a string setting named **Discount Type** (as textual values tell more than numbers).
The go-to feature for A/B testing is Percentage Options. So let's add one with 3 options, each covering 1/3rd of our customers.

info
To make all this useful, that is, to measure the effectiveness of the different strategies, we also need to integrate with an analytics service like [Amplitude](https://configcat.com/docs/integrations/amplitude.md) or [Mixpanel](https://configcat.com/docs/integrations/mixpanel.md) and update our application to send feature flag evaluation results to it.
##### Complex phased rollout / Canary release / Percentage rollout scenario[](#complex-phased-rollout--canary-release--percentage-rollout-scenario "Direct link to Complex phased rollout / Canary release / Percentage rollout scenario")
###### Context[](#context-2 "Direct link to Context")
Whisker Co. is about to release a new feature called **Park Weather Info**. The stakeholders want to make sure that the release of the new feature goes smoothly and it is received well by the customers.
###### Goal[](#goal-2 "Direct link to Goal")
To do some in-house testing and also get some feedback from our customers before releasing it to everyone, we initially want to make the feature available to the employees and to 20% of the customers only.
###### Solution[](#solution-2 "Direct link to Solution")
Let's create a feature flag called **Enable Park Weather Info** with a Targeting Rule that matches the employees at Whisker Co. and Percentage Options set to **20% ON** and **80% OFF** for the rest of the users (i.e. for the customers).

##### Platform-specific phased rollout[](#platform-specific-phased-rollout "Direct link to Platform-specific phased rollout")
###### Context[](#context-3 "Direct link to Context")
Whisker Co. is about to release a new feature called **Cafe Notifications** in their mobile app, which has an Android and an iOS version. We know that the userbase of the iOS app is much larger than the Android app. The stakeholders want to make sure that the new feature is received well by the customers.
###### Goal[](#goal-3 "Direct link to Goal")
To get some feedback from our customers before releasing it to everyone, we initially want to make the feature available to a limited number of customers only. We also want to release the feature to roughly the same number of Android and iOS users.
###### Solution[](#solution-3 "Direct link to Solution")
Let's create a feature flag called **Cafe Notifications** with two Targeting Rules: one that matches Android users and one that matches iOS users. Then change the THEN part of both to Percentage Options. Finally, let's set the percentages so that the feature is enabled for roughly the same number of users (e.g. 60% for Android users, 20% for iOS users).

##### Percentage Options based on other user attributes[](#percentage-options-based-on-other-user-attributes "Direct link to Percentage Options based on other user attributes")
###### Context[](#context-4 "Direct link to Context")
Let's imagine that at Whisker Co., we have a custom attribute named **Tenant ID** that is used to identify the tenants of our customers.
###### Goal[](#goal-4 "Direct link to Goal")
We want to release a new feature, **Park Weather Info**, to 20% of our customers based on their **Tenant ID**.
###### Solution[](#solution-4 "Direct link to Solution")
Let's create a feature flag called **Enable Park Weather Info** with Percentage Options set to **20% ON** and **80% OFF**. Finally, let's set the Percentage Evaluation Attribute to **Tenant ID** as described [here](#percentage-evaluation-attribute).

---
### Targeting Overview
Copy page
Targeting allows you to enable or disable a feature for specific users or groups of users in your application. Typical use cases are:
* [Beta testing](https://configcat.com/docs/glossary.md#beta-testing)
* [A/B testing](https://configcat.com/docs/glossary.md#ab-testing)
* [Phased rollouts, canary releases](https://configcat.com/docs/glossary.md#canary-release)
#### How does it work?[](#how-does-it-work "Direct link to How does it work?")
1. On the [ConfigCat Dashboard](https://app.configcat.com), you add [Targeting Rules](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md) and/or [Percentage Options](https://configcat.com/docs/targeting/percentage-options.md) to your feature flag.
2. You pass a [User Object](https://configcat.com/docs/targeting/user-object.md) to the ConfigCat SDK in your application.
3. The ConfigCat SDK will use the User Object and the rules defined on the Dashboard to determine whether the feature should be enabled for the user.
#### What is what?[](#what-is-what "Direct link to What is what?")

##### Feature Flag / Setting[](#feature-flag--setting "Direct link to Feature Flag / Setting")
A *setting* is a set of rules that yields a **boolean**, **string**, **integer** or **double** value, which can be used to configure your application. It is also known as a configuration value, configuration setting, configuration parameter, etc.
A *feature flag* is a **boolean** setting used to decide whether an application feature should be turned ON or OFF. It is also known as a feature toggle, feature switch, feature flipper, conditional feature, etc.
info
Throughout this documentation, we generally use the term *feature flag* to refer to both feature flags and settings for simplicity because feature flags are the most common type of settings.
##### Targeting Rule[](#targeting-rule "Direct link to Targeting Rule")
A *Targeting Rule* consists of a collection of conditions and a value to serve. If the conditions are met (the Targeting Rule *matches*), the value is served, i.e. returned as the result of the feature flag evaluation. More about Targeting Rules [here](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md).
##### Condition[](#condition "Direct link to Condition")
A *condition* is a logical expression that can be evaluated to true or false. There are three types of conditions: [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md), [Flag Condition (Prerequisite)](https://configcat.com/docs/targeting/targeting-rule/flag-condition.md), [Segment Condition](https://configcat.com/docs/targeting/targeting-rule/segment-condition.md). For a Targeting Rule to match, all of its conditions must evaluate to true.
##### Percentage Options[](#percentage-options "Direct link to Percentage Options")
*Percentage Options* divide users into groups, each receiving a specific value. The groups are allocated according to the specified percentage split. Percentage Options are often used for A/B testing or phased rollouts. More about Percentage Options [here](https://configcat.com/docs/targeting/percentage-options.md).
##### "To all users" / "To all other" / "To unidentified" value[](#to-all-users--to-all-other--to-unidentified-value "Direct link to \"To all users\" / \"To all other\" / \"To unidentified\" value")
A feature flag always contains a trivial "rule", a simple value after the actual rules. This value is returned when none of the preceding rules yields a result.
##### Default value[](#default-value "Direct link to Default value")
The ConfigCat SDK's feature flag evaluation functions (e.g. `GetValue`) require you to provide a *default value*. This value will be returned in case the SDK fails to fetch the config or some other error occurs during the evaluation of the feature flag.
##### User Object[](#user-object "Direct link to User Object")
A *User Object* is a collection of *user attributes* that describe the properties of a user. Referencing these attributes in conditions allows you to define rules for targeting users. More about the User Object [here](https://configcat.com/docs/targeting/user-object.md).
#### Examples[](#examples "Direct link to Examples")
##### Phased rollout / Canary release / Percentage rollout scenario[](#phased-rollout--canary-release--percentage-rollout-scenario "Direct link to Phased rollout / Canary release / Percentage rollout scenario")
###### Context[](#context "Direct link to Context")
Our demo company, Whisker Co. is about to release a new feature called **Park Weather Info**. The stakeholders want to make sure that the release of the new feature goes smoothly and it is received well by the customers.
###### Goal[](#goal "Direct link to Goal")
To make sure that the new feature is working as expected before releasing it to everyone, we initially want to make the feature available to the employees and to 20% of the customers only.
###### Solution[](#solution "Direct link to Solution")
Let's create a feature flag called **Enable Park Weather Info** with a Targeting Rule that matches the employees at Whisker Co. and Percentage Options set to **20% ON** and **80% OFF** for the rest of the users (i.e. for the customers).
Here is what such a feature flag looks like on the Dashboard:

Here is how we get the value of the feature flag in your application:
```js
// Create the User Object
const userObject = {
// Used by the Percentage Options to split the users into groups
identifier: '867428724',
// Used by the Targeting Rule's User Condition to determine whether
// the user is an employee at Whisker Co.
email: 'isaac@whisker.cc',
};
// Get the value of the feature flag
const value = await configCatClient.getValueAsync(
// Feature flag key
'enableParkWeatherInfo',
// Default value - by providing `false` we specify that the feature should not be
// enabled if the SDK fails to fetch the config or some other error occurs
false,
// User Object
userObject,
);
```
---
### Flag Condition (Prerequisite)
Copy page
#### What is a Flag Condition? What is a prerequisite flag?[](#what-is-a-flag-condition-what-is-a-prerequisite-flag "Direct link to What is a Flag Condition? What is a prerequisite flag?")
A *Flag Condition* is a condition that is based on the comparison of another feature flag's value and a preset value (*comparison value*). In other words, a Flag Condition creates a dependency between the feature flag containing the condition (*dependent flag*) and another feature flag (*prerequisite flag*, aka. master feature flag, master switch, inter-dependent feature flag, global toggle, etc.)
This allows you to control the value of multiple feature flags by changing the value of a single, central feature flag. Prerequisite flags are useful for managing complex feature dependencies and ensuring a smooth user experience during feature rollouts.
#### How does the Flag Condition work?[](#how-does-the-flag-condition-work "Direct link to How does the Flag Condition work?")
The prerequisite flag is evaluated with the same User Object as the one used to evaluate the dependent flag, and then the result is checked against the comparator that you set on the Dashboard.
The prerequisite flag can be other than a feature flag (boolean setting), in which case the prerequisite flag's evaluated value will be compared to the comparison value that you set on the Dashboard. The comparison is done according to the selected comparator and will result in true or false. This will be the result of the condition.
For more details on the evaluation of Flag Conditions, please refer to [Feature Flag Evaluation](https://configcat.com/docs/targeting/feature-flag-evaluation.md#evaluation-of-a-flag-condition).
#### How to set a Flag Condition?[](#how-to-set-a-flag-condition "Direct link to How to set a Flag Condition?")
You can add a Flag Condition to a feature flag by clicking the **+IF** ("Add targeting rule") button on the Dashboard.
The prerequisite flag can be any feature flag already defined in the same config on the Dashboard. In the case of a non-boolean setting (e.g. text setting or number setting), you can also set a comparison value which the prerequisite flag's value will be compared to.

#### Anatomy of a Flag Condition[](#anatomy-of-a-flag-condition "Direct link to Anatomy of a Flag Condition")
###### Prerequisite is a feature flag (boolean setting)[](#prerequisite-is-a-feature-flag-boolean-setting "Direct link to Prerequisite is a feature flag (boolean setting)")

###### Prerequisite is a string, integer or double setting[](#prerequisite-is-a-string-integer-or-double-setting "Direct link to Prerequisite is a string, integer or double setting")

A Flag Condition consists of the following:
* ***Prerequisite flag key*:** The key of the feature flag or setting on which the condition is based.
* ***Comparator*:** The comparison operator that defines the relation between the prerequisite flag's value and the comparison value. See the available comparators below.
* ***Comparison value*:** The value that the prerequisite flag's value is compared to. Available only when the prerequisite flag is a string, integer or double setting.
##### Comparator[](#comparator "Direct link to Comparator")
Different comparators are available for different types of prerequisites.
When the prerequisite is a feature flag (boolean setting), the following comparators are available:
| Comparator | Description |
| ---------- | -------------------------------------------- |
| IS ON | Checks whether the prerequisite flag is ON. |
| IS OFF | Checks whether the prerequisite flag is OFF. |
When the prerequisite is a string, integer or double setting, the following comparators are available:
| Comparator | Description |
| ---------- | ---------------------------------------------------------------------------------- |
| EQUALS | Checks whether the prerequisite flag's value is equal to the comparison value. |
| NOT EQUALS | Checks whether the prerequisite flag's value is not equal to the comparison value. |
#### Examples[](#examples "Direct link to Examples")
##### Enable feature depending on the availability of another one[](#enable-feature-depending-on-the-availability-of-another-one "Direct link to Enable feature depending on the availability of another one")
###### Context[](#context "Direct link to Context")
Our demo company, Whisker Co. has a mobile app, which, among other things, can show the cat-friendly cafés in the neighborhood.
The app can send notifications about the users' favorite cafés. This feature is not available to everyone though, it's enabled using the **Enable Cafe Notifications** feature flag. There is another feature that allows users to rate cafés, whose availability is controlled similarly, via the **Enable Cafe Ratings** feature flag.
###### Goal[](#goal "Direct link to Goal")
We want to make sure that users only receive notifications about their favorite cafés if they can rate them.
###### Solution[](#solution "Direct link to Solution")
ConfigCat offers a built-in way to solve this problem without the need of extra coding: prerequisite flags.
We can achieve our goal by adding a Targeting Rule containing a Flag Condition to **Enable Cafe Notifications**, then referencing **Enable Cafe Ratings** in the condition and setting the comparator to **IS ON**, meaning that the **Enable Cafe Notifications** feature flag will be enabled only if the **Enable Cafe Ratings** feature flag is ON.
On the Dashboard:

---
### Segment Condition
Copy page
#### What is a Segment Condition? What is a segment?[](#what-is-a-segment-condition-what-is-a-segment "Direct link to What is a Segment Condition? What is a segment?")
A *Segment Condition* is a condition that is based on the evaluation of a segment. A *segment* is approximately a reusable, predefined [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md).
Segments allow you to define user groups based on any user attribute. You can reference segments in Targeting Rules. When you update a segment definition, the changes will be reflected automatically in all the Targeting Rules that reference it.
For example, you can define a segment called **Beta Testers** and use that segment for all features you want to be available to beta testers.
One segment belongs to one product and can be used in multiple feature flags within the same product.
#### How does the Segment Condition work?[](#how-does-the-segment-condition-work "Direct link to How does the Segment Condition work?")
The segment is evaluated with the [User Object](https://configcat.com/docs/targeting/user-object.md). Then the result is checked against the comparator you set on the Dashboard:
* For **IS IN SEGMENT**, the result of the Segment Condition will be the same as the result of the segment itself.
* For **IS NOT IN SEGMENT**, the result will be negated (i.e. it will be the opposite of the result of the segment).
For more details on the evaluation of Segment Conditions, please refer to [Feature Flag Evaluation](https://configcat.com/docs/targeting/feature-flag-evaluation.md#evaluation-of-a-segment-condition).
#### How to set a Segment Condition?[](#how-to-set-a-segment-condition "Direct link to How to set a Segment Condition?")
You can add a Segment Condition to a feature flag by clicking the **+IF** ("Add targeting rule") button on the Dashboard.

#### Where can I define segments?[](#where-can-i-define-segments "Direct link to Where can I define segments?")
You can define your segments on the ConfigCat Dashboard, on the [Segments page](https://app.configcat.com/product/segments).

#### Anatomy of a Segment Condition[](#anatomy-of-a-segment-condition "Direct link to Anatomy of a Segment Condition")

A Segment Condition consists of two parts:
* ***Segment comparator*:** The comparison operator defines the relation between the user and the segment. See the available comparators below.
* ***Segment*:** The segment that the condition is based on.
##### Segment comparator[](#segment-comparator "Direct link to Segment comparator")
| Comparator | Description |
| ----------------- | ------------------------------------------------------- |
| IS IN SEGMENT | Checks whether the user is in the selected segment. |
| IS NOT IN SEGMENT | Checks whether the user is not in the selected segment. |
#### Anatomy of a Segment[](#anatomy-of-a-segment "Direct link to Anatomy of a Segment")
| Field | Purpose |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name | The name of the segment. |
| Description | The description of the segment. It's a good idea to add a hint that helps you remember what the segment is for. |
| Comparison attribute | The attribute that the segment is based on. Can be **Identifier** (user ID), **Email**, **Country**, or any custom attribute. |
| Comparator | The comparison operator. Defines the relation between the comparison attribute and the comparison value. |
| Comparison value | The value that the attribute is compared to. Can be a string, a number, a semantic version or a comma-separated list, depending on the comparator. |
##### Comparison attribute[](#comparison-attribute "Direct link to Comparison attribute")
A property of your user (e.g. email address, geographic location). Your application should pass the attribute values (e.g. `'jane@example.com'`, `'Europe'`) to the ConfigCat SDK as a [User Object](https://configcat.com/docs/targeting/user-object.md).
There are 3 predefined attributes. Additionally, you can define your custom attributes as well:
| Comparison attribute name | Description |
| ------------------------- | --------------------------------------------------------------------------------------------------- |
| Identifier | Usually, it is a unique user identifier in your application. |
| Email | The e-mail address of your user. |
| Country | The location of your user. Might be useful for testing a new feature in specific countries only. |
| Custom | Any additional attribute (e.g. **OS version**). Can be defined by typing its name into the textbox. |
##### Comparison value[](#comparison-value "Direct link to Comparison value")
Any string, number, or comma-separated list. Will be compared to the selected comparison attribute using the comparator. **Max. length: 65535 characters.**
##### Comparator[](#comparator "Direct link to Comparator")
###### Confidential text comparators[](#confidential-text-comparators "Direct link to Confidential text comparators")
We recommend using confidential text comparators when targeting users based on their sensitive data (like email address, name, etc.) In this case, the feature flag evaluation is performed using the SHA256 hashes of the values to ensure that the comparison values are not exposed. This can cause an increase in the size of the config JSON file and the overall network traffic. Yet it is not recommended to use the cleartext version of the confidential comparators unless the increased network traffic becomes an issue.
The following comparators expect the comparison attribute to be a string value and the comparison value to be a string or a list of strings. The comparison is case-sensitive.
| Comparator | Description |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| IS ONE OF (hashed) | Checks whether the comparison attribute is equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list.) |
| IS NOT ONE OF (hashed) | Checks whether the comparison attribute is not equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list.) |
###### Text comparators[](#text-comparators "Direct link to Text comparators")
The following comparators expect the comparison attribute to be a string value and the comparison value to be a string or a list of strings. The comparison is case-sensitive.
info
Consider using confidential text comparators if you plan to target users based on their sensitive data, e.g. email address or company domain.
| Comparator | Description |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| CONTAINS (cleartext) | Checks whether the comparison attribute contains the comparison value as a substring. |
| DOES NOT CONTAIN (cleartext) | Checks whether the comparison attribute does not contain the comparison value as a substring. |
| IS ONE OF (cleartext) | Checks whether the comparison attribute is equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list.) |
| IS NOT ONE OF (cleartext) | Checks whether the comparison attribute is not equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list.) |
###### Semantic version comparators[](#semantic-version-comparators "Direct link to Semantic version comparators")
The following comparators expect the comparison attribute to be a string containing a valid semantic version and the comparison value to be a semantic version or a list of semantic versions.
Comparison is performed according to the [Semantic Versioning specification](https://semver.org/).
| Comparator | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| IS ONE OF (semver) | Checks whether the comparison attribute interpreted as a semantic version is equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list of semantic versions.) |
| IS NOT ONE OF (semver) | Checks whether the comparison attribute interpreted as a semantic version is not equal to any of the comparison values. (Comparison value is interpreted as a comma-separated list of semantic versions.) |
| < (semver) | Checks whether the comparison attribute interpreted as a semantic version is less than the comparison value. |
| <= (semver) | Checks whether the comparison attribute interpreted as a semantic version is less than or equal to the comparison value. |
| > (semver) | Checks whether the comparison attribute interpreted as a semantic version is greater than the comparison value. |
| >= (semver) | Checks whether the comparison attribute interpreted as a semantic version is greater than or equal to the comparison value. |
###### Number comparators[](#number-comparators "Direct link to Number comparators")
The following comparators expect the comparison attribute and the comparison value to be numbers.
| Comparator | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| = (number) | Checks whether the comparison attribute interpreted as a decimal number is equal to the comparison value. |
| <> (number) | Checks whether the comparison attribute interpreted as a decimal number is not equal to the comparison value. |
| < (number) | Checks whether the comparison attribute interpreted as a decimal number is less than the comparison value. |
| <= (number) | Checks whether the comparison attribute interpreted as a decimal number is less than or equal to the comparison value. |
| > (number) | Checks whether the comparison attribute interpreted as a decimal number is greater than the comparison value. |
| >= (number) | Checks whether the comparison attribute interpreted as a decimal number is greater than or equal to the comparison value. |
#### Examples[](#examples "Direct link to Examples")
##### Beta testing scenario[](#beta-testing-scenario "Direct link to Beta testing scenario")
###### Context[](#context "Direct link to Context")
The developers at our demo company, Whisker Co. just finished implementing a nice new feature which allows users to personalize the layout of the webshop. It's time for a beta test.
###### Goal[](#goal "Direct link to Goal")
We want to make the **Personalized Layout** feature of the webshop available to the beta testers.
###### Solution[](#solution "Direct link to Solution")
We could simply achieve our goal using a Targeting Rule with a User Condition. However, **Personalized Layout** is certainly not the last feature developed at Whisker Co., so it's a good idea to create a segment named e.g. **Beta Testers** for our beta testers. This makes it easier for us to release further features for beta testing in the future.
After creating the segment, we can complete our task by adding a Targeting Rule containing a Segment Condition to **Enable Personalized Layout**, then referencing the **Beta Testers** segment in the condition and setting the comparator to **IS IN SEGMENT**.
On the Dashboard:

---
### Targeting Rule
Copy page
#### What is a Targeting Rule?[](#what-is-a-targeting-rule "Direct link to What is a Targeting Rule?")
*Targeting Rules* allow you to set different feature flag values for specific users or groups of users in your application.
You can set conditions based on user attributes, feature flags, or segments within a Targeting Rule.
##### AND and OR relationships[](#and-and-or-relationships "Direct link to AND and OR relationships")
The conditions within a Targeting Rule are in an **AND** relationship, meaning that all of them must evaluate to true for the Targeting Rule to match.
The Targeting Rules are in an **OR** relationship, meaning that the Targeting Rule which matches first in order, from top to bottom, will provide the value of the feature flag.
#### How to add a Targeting Rule?[](#how-to-add-a-targeting-rule "Direct link to How to add a Targeting Rule?")
You can add a Targeting Rule to a feature flag by clicking the **+IF** ("Add targeting rule") button on the Dashboard. To add more Targeting Rules, click the **+OR** button at the bottom of the last Targeting Rule.

#### How does it work? - Anatomy of a Targeting Rule[](#how-does-it-work---anatomy-of-a-targeting-rule "Direct link to How does it work? - Anatomy of a Targeting Rule")
A Targeting Rule consists of an *IF part* and a *THEN part*.

##### IF part[](#if-part "Direct link to IF part")
The *IF part* contains the conditions, which are logical expressions that evaluate to true or false.
The conditions are in an **AND** relationship, meaning that all of them must evaluate to true for the Targeting Rule to match.
The conditions can be added to the Targeting Rule on the Dashboard, using the **+AND** ("Add AND condition") button. There are three types of conditions:
* [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md) - A condition that is based on some property of the user.
* [Flag Condition (Prerequisite)](https://configcat.com/docs/targeting/targeting-rule/flag-condition.md) - A condition that is based on the value of another feature flag.
* [Segment Condition](https://configcat.com/docs/targeting/targeting-rule/segment-condition.md) - A condition that is based on a segment.
##### THEN part[](#then-part "Direct link to THEN part")
The *THEN part* determines the result of the feature flag when the Targeting Rule matches. It can be either a simple value or Percentage Options.
#### Multiple Targeting Rules and ordering[](#multiple-targeting-rules-and-ordering "Direct link to Multiple Targeting Rules and ordering")
The order of Targeting Rules matters because they are in an **OR** relationship, meaning that the Targeting Rule which matches first in order, from top to bottom, will provide the value of the feature flag.
##### How to change the order of the Targeting Rules?[](#how-to-change-the-order-of-the-targeting-rules "Direct link to How to change the order of the Targeting Rules?")
The order of the Targeting Rules can be changed on the Dashboard by dragging and dropping the Targeting Rules.

#### Examples[](#examples "Direct link to Examples")
##### AND relationship between Conditions[](#and-relationship-between-conditions "Direct link to AND relationship between Conditions")
###### Context[](#context "Direct link to Context")
In our demo company (Whisker Co.) we have a new feature in our mobile app that notifies frequent shopper cat owners about the cat-friendly cafés in the neighborhood.
###### Goal[](#goal "Direct link to Goal")
Since this feature is new, we want to make sure that only frequent shoppers and cat owners who have the right version of the app receive these notifications. The earlier versions of the app don't have this feature, so we want to make sure that only those who are running version 3.0.0 or higher receive the notifications.
###### Solution[](#solution "Direct link to Solution")
We can achieve this by adding a Targeting Rule to the **Enable Cafe Notifications** feature flag. The Targeting Rule will have two conditions:
* a Segment Condition, which requires that the user is in segment **Frequent Shoppers**,
* a User Condition, which requires that the user attribute **AppVersion** is greater than or equal to **3.0.0**.
On the Dashboard:

In the code:
```js
const userObject = {
identifier: userId,
email: userEmail,
custom: {
AppVersion: '3.1.2'
},
};
const value = await configCatClient.getValueAsync("enableCafeNotifications", false, userObject);
```
---
### User Condition
Copy page
#### What is a User Condition?[](#what-is-a-user-condition "Direct link to What is a User Condition?")
A *User Condition* is a condition that is based on the comparison of a user attribute (*comparison attribute*) and a preset value (*comparison value*).
It allows you to define Targeting Rules which target users based on their properties.
#### How does the User Condition work?[](#how-does-the-user-condition-work "Direct link to How does the User Condition work?")
The comparison attribute's value from the [User Object](https://configcat.com/docs/targeting/user-object.md) is compared to the comparison value you set on the Dashboard. The comparison is done according to the selected comparator and will result in true or false. This will be the result of the condition.
For more details on the evaluation of User Conditions, please refer to [Feature Flag Evaluation](https://configcat.com/docs/targeting/feature-flag-evaluation.md#evaluation-of-a-user-condition).
#### How to set a User Condition?[](#how-to-set-a-user-condition "Direct link to How to set a User Condition?")
You can add a User Condition to a feature flag by clicking the **+IF** ("Add targeting rule") button on the Dashboard. To add more conditions, click the **+AND** ("Add AND condition") button.

#### Anatomy of a User Condition[](#anatomy-of-a-user-condition "Direct link to Anatomy of a User Condition")

A User Condition consists of three parts:
* ***Comparison attribute*:** The user attribute on which the condition is based. Can be **Identifier** (user ID), **Email**, **Country**, or any custom attribute.
* ***Comparator*:** The comparison operator that defines the relation between the comparison attribute and the comparison value. See the available comparators [here](#comparator).
* ***Comparison value*:** The preset value to which the comparison attribute is compared. Depending on the comparator, can be a string, a list of strings, a number, a semantic version, a list of semantic versions or a date.
##### Comparison attribute[](#comparison-attribute "Direct link to Comparison attribute")
A property of your user (e.g. email address, geographic location). Your application should pass the attribute values (e.g. `'jane@example.com'`, `'Europe'`) to the ConfigCat SDK as a [User Object](https://configcat.com/docs/targeting/user-object.md).
There are 3 predefined attributes. Additionally, you can define your custom attributes as well:
| Comparison attribute name | Description |
| ------------------------- | --------------------------------------------------------------------------------------------------- |
| Identifier | Usually, it is a unique user identifier in your application. |
| Email | The e-mail address of your user. |
| Country | The location of your user. Might be useful for testing a new feature in specific countries only. |
| Custom | Any additional attribute (e.g. **OS version**). Can be defined by typing its name into the textbox. |
##### Comparison value[](#comparison-value "Direct link to Comparison value")
A string, a list of strings, a number, a semantic version, a list of semantic versions or a date value. Will be compared to the selected comparison attribute using the comparator. The length of the comparison value is limited, and the limit depends on your subscription plan. See the [Subscription Plan Limits page](https://configcat.com/docs/subscription-plan-limits.md) for more details.
##### Comparator[](#comparator "Direct link to Comparator")
###### Confidential text comparators[](#confidential-text-comparators "Direct link to Confidential text comparators")
We recommend using confidential text comparators when targeting users based on their sensitive data (like email address, name, etc.) In this case, the feature flag evaluation is performed using the SHA256 hashes of the values to ensure that the comparison values are not exposed. This can cause an increase in the size of the config JSON file and the overall network traffic. Yet it is not recommended to use the cleartext version of the confidential comparators unless the increased network traffic becomes an issue.
The following comparators expect the comparison attribute to be a string value and the comparison value to be a string or a list of strings. The comparison is case-sensitive.
| Comparator | Description |
| ------------------------------- | ----------------------------------------------------------------------------------------- |
| EQUALS (hashed) | Checks whether the comparison attribute is equal to the comparison value. |
| NOT EQUALS (hashed) | Checks whether the comparison attribute is not equal to the comparison value. |
| IS ONE OF (hashed) | Checks whether the comparison attribute is equal to any of the comparison values. |
| IS NOT ONE OF (hashed) | Checks whether the comparison attribute is not equal to any of the comparison values. |
| STARTS WITH ANY OF (hashed) | Checks whether the comparison attribute starts with any of the comparison values. |
| NOT STARTS WITH ANY OF (hashed) | Checks whether the comparison attribute does not start with any of the comparison values. |
| ENDS WITH ANY OF (hashed) | Checks whether the comparison attribute ends with any of the comparison values. |
| NOT ENDS WITH ANY OF (hashed) | Checks whether the comparison attribute does not end with any of the comparison values. |
###### Text comparators[](#text-comparators "Direct link to Text comparators")
The following comparators expect the comparison attribute to be a string value and the comparison value to be a string or a list of strings. The comparison is case-sensitive.
info
Consider using confidential text comparators if you plan to target users based on their sensitive data, e.g. email address or company domain.
| Comparator | Description |
| ---------------------------------- | ---------------------------------------------------------------------------------------------- |
| EQUALS (cleartext) | Checks whether the comparison attribute is equal to the comparison value. |
| NOT EQUALS (cleartext) | Checks whether the comparison attribute is not equal to the comparison value. |
| IS ONE OF (cleartext) | Checks whether the comparison attribute is equal to any of the comparison values. |
| IS NOT ONE OF (cleartext) | Checks whether the comparison attribute is not equal to any of the comparison values. |
| STARTS WITH ANY OF (cleartext) | Checks whether the comparison attribute starts with any of the comparison values. |
| NOT STARTS WITH ANY OF (cleartext) | Checks whether the comparison attribute does not start with any of the comparison values. |
| ENDS WITH ANY OF (cleartext) | Checks whether the comparison attribute ends with any of the comparison values. |
| NOT ENDS WITH ANY OF (cleartext) | Checks whether the comparison attribute does not end with any of the comparison values. |
| CONTAINS ANY OF (cleartext) | Checks whether the comparison attribute contains any comparison values as a substring. |
| NOT CONTAINS ANY OF (cleartext) | Checks whether the comparison attribute does not contain any comparison values as a substring. |
###### Semantic version comparators[](#semantic-version-comparators "Direct link to Semantic version comparators")
The following comparators expect the comparison attribute to be a string containing a valid semantic version and the comparison value to be a semantic version or a list of semantic versions.
Comparison is performed according to the [Semantic Versioning specification](https://semver.org/).
| Comparator | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| IS ONE OF (semver) | Checks whether the comparison attribute interpreted as a semantic version is equal to any of the comparison values. |
| IS NOT ONE OF (semver) | Checks whether the comparison attribute interpreted as a semantic version is not equal to any of the comparison values. |
| < (semver) | Checks whether the comparison attribute interpreted as a semantic version is less than the comparison value. |
| <= (semver) | Checks whether the comparison attribute interpreted as a semantic version is less than or equal to the comparison value. |
| > (semver) | Checks whether the comparison attribute interpreted as a semantic version is greater than the comparison value. |
| >= (semver) | Checks whether the comparison attribute interpreted as a semantic version is greater than or equal to the comparison value. |
###### Number comparators[](#number-comparators "Direct link to Number comparators")
The following comparators expect the comparison attribute and the comparison value to be numbers.
| Comparator | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| = (number) | Checks whether the comparison attribute interpreted as a decimal number is equal to the comparison value. |
| <> (number) | Checks whether the comparison attribute interpreted as a decimal number is not equal to the comparison value. |
| < (number) | Checks whether the comparison attribute interpreted as a decimal number is less than the comparison value. |
| <= (number) | Checks whether the comparison attribute interpreted as a decimal number is less than or equal to the comparison value. |
| > (number) | Checks whether the comparison attribute interpreted as a decimal number is greater than the comparison value. |
| >= (number) | Checks whether the comparison attribute interpreted as a decimal number is greater than or equal to the comparison value. |
###### Date and time comparators[](#date-and-time-comparators "Direct link to Date and time comparators")
The following comparators expect the comparison attribute to be a date value (a second-based [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) or a platform-specific date object) and the comparison value to be a date.
| Comparator | Description |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BEFORE | Checks whether the comparison attribute interpreted as a second-based [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) is less than the comparison value. |
| AFTER | Checks whether the comparison attribute interpreted as a second-based [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) is greater than the comparison value. |
###### Array comparators[](#array-comparators "Direct link to Array comparators")
The following comparators expect the comparison attribute to be an array of strings (or an array of strings serialized to JSON) and the comparison value to be a list of strings. The comparison is case-sensitive.
| Comparator | Description |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| ARRAY CONTAINS ANY OF | Checks whether the comparison attribute interpreted as an array of strings contains any of the comparison values. |
| ARRAY NOT CONTAINS ANY OF | Checks whether the comparison attribute interpreted as an array of strings does not contain any of the comparison values |
#### Examples[](#examples "Direct link to Examples")
##### Black Friday sale[](#black-friday-sale "Direct link to Black Friday sale")
###### Context[](#context "Direct link to Context")
Black Friday is coming and we want to offer a special discount to our users.
###### Goal[](#goal "Direct link to Goal")
The deals should become available at midnight on Black Friday. We want to make sure that the users can't access the deals before that. Also, the deals should be available for the whole weekend.
###### Solution[](#solution "Direct link to Solution")
Let's use the **AFTER** comparator to check whether the current time is after midnight on Black Friday AND the current time is **BEFORE** midnight on Sunday.
On the Dashboard:

In the code:
```js
const userObject = {
identifier: userId,
email: userEmail,
custom: {
// In case this code runs on the customer's device, we should consider getting the current time
// from a time server since customers are free to set the system clock on their devices.
Date: new Date()
},
};
const value = await configCatClient.getValueAsync("enableBlackFridayDeals", false, userObject);
```
##### Confidential CONTAINS and NOT CONTAINS workaround[](#confidential-contains-and-not-contains-workaround "Direct link to Confidential CONTAINS and NOT CONTAINS workaround")
###### Context[](#context-1 "Direct link to Context")
We use ConfigCat in our Angular frontend application to control the availability of a feature.
###### Goal[](#goal-1 "Direct link to Goal")
We want to enable this feature for users from certain companies. To do the job, we would need to use the **CONTAINS** or **NOT CONTAINS** comparators.
However, there is no confidential version of these comparators and we are well aware that, for privacy reasons, it's not a good idea to use cleartext comparators for applications running in the browser.
How can we solve this?
###### Solution[](#solution-1 "Direct link to Solution")
Let's work around the problem by extracting the domain part of the email and passing it as a custom attribute named **Domain** to the ConfigCat SDK.
This way we can define the desired Targeting Rule using confidential comparators only.
On the Dashboard:

In the code:
```js
const userDomain = userEmail.split('@').pop();
const userObject = {
identifier: userId,
email: userEmail,
custom: {
Domain: userDomain
},
};
const value = await configCatClient.getValueAsync(key, defaultValue, userObject);
```
info
Since the introduction of [Config V2](https://configcat.com/docs/advanced/config-v2.md), this workaround is no longer needed: in a V2 config, you can simply use the hashed version of the **ENDS WITH ANY OF** comparator.
---
### User Object
Copy page
The *User Object* represents a user in your application. It is a collection of *user attributes* that store various pieces of information about the user.
The User Object is necessary to evaluate [Targeting Rules](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md) and [Percentage Options](https://configcat.com/docs/targeting/percentage-options.md). It allows you to pass the user attributes that are referenced in the rules of the feature flag to the ConfigCat SDK.
info
The User Object is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
#### The relationship between the User Object and Targeting Rules[](#the-relationship-between-the-user-object-and-targeting-rules "Direct link to The relationship between the User Object and Targeting Rules")
**As a product manager**, you can define [Targeting Rules](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md) on the [ConfigCat Dashboard](https://app.configcat.com) based on the user attributes that are provided by your application.
**As a developer**, User Object allows you to pass user attributes to the ConfigCat SDK, which you (or your teammates) can reference in the [Targeting Rules](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md) on the [Dashboard](https://app.configcat.com).
#### Security and privacy concerns[](#security-and-privacy-concerns "Direct link to Security and privacy concerns")
ConfigCat was designed with security and privacy in mind. The feature flag evaluation process is entirely implemented within the SDKs, meaning **your users' sensitive data never leaves your system**. The data flow is one-way – from ConfigCat CDN servers to your SDKs – and ConfigCat does not receive or store any attributes of the User Object passed to the SDKs. This design prioritizes the privacy and security of user data.
#### Anatomy of the User Object[](#anatomy-of-the-user-object "Direct link to Anatomy of the User Object")
The User Object offers the following properties to store user data:
| Attribute | Description |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Identifier | **REQUIRED.** We recommend using a user ID, email address, or session ID. |
| Email | Optional. Set this if you want to target users based on their email address. E.g.: "Turn on a feature for users with **@example.com** addresses only." |
| Country | Optional. Specify this for location or country-based targeting. E.g.: "Turn on a feature for users in Canada only." |
| Custom | Optional. A map/dictionary that lets you set custom user attributes to target users based on any user data. E.g.: age, subscription type, user role, device type, app version, etc. |
##### Code example[](#code-example "Direct link to Code example")
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#', // required
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
##### Identifier attribute[](#identifier-attribute "Direct link to Identifier attribute")
The unique identifier of a user in your application. This is a **REQUIRED** attribute. ConfigCat uses this attribute to differentiate your users from each other. By default, it is used to evaluate [Percentage Options](https://configcat.com/docs/targeting/percentage-options.md).
Our recommendation for an identifier:
* User ID - You can simply use the user ID native to your application.
* Email address - In most cases, using an email address works perfectly - as long as it is unique.
* Session ID - This is useful for targeting users who are not logged in to your application.
##### Custom attributes[](#custom-attributes "Direct link to Custom attributes")
To use custom attributes, you need to pass a User Object containing the `custom` property to the ConfigCat SDK.
info
The custom attribute's value can be of multiple types: e.g. string, number, date, array of strings, etc. Check the [SDK reference](https://configcat.com/docs/sdk-reference/overview.md) for more details.
#### Examples[](#examples "Direct link to Examples")
##### Enable a feature for most valuable customers only[](#enable-a-feature-for-most-valuable-customers-only "Direct link to Enable a feature for most valuable customers only")
###### Context[](#context "Direct link to Context")
Our demo company, Whisker Co. developed a new feature called **Personalized Layout** to enhance the user experience of their most valuable customers.
###### Goal[](#goal "Direct link to Goal")
We want to enable the **Personalized Layout** feature but only for customers with the **Pro** subscription.
###### Solution[](#solution "Direct link to Solution")
To achieve this goal, we need a custom attribute named e.g. **SubscriptionType**, which stores the subscription type of the customer.
This allows us to define a Targeting Rule that turns on the feature for the customers whose **SubscriptionType** attribute is **Pro**. Finally, we need to make sure that the "To all others" value is **OFF** so the feature is turned off for the rest of the customers.
###### Dashboard[](#dashboard "Direct link to Dashboard")

###### Code[](#code "Direct link to Code")
Add the **SubscriptionType** custom attribute to the User Object in your application code.
```js
const userObject = {
identifier: userId,
custom: {
SubscriptionType: 'Pro',
},
};
```
---
## What is a JSON download?
### What is a config JSON download?
Copy page
A config JSON download is counted every time your application downloads a configuration file from the ConfigCat CDN. The frequency of these downloads is totally under your control. Between downloads, you can evaluate your feature flags as many times as you like, it still counts as one config JSON download.
See an [overview of the ConfigCat architecture](https://configcat.com/architecture/).
Use the [Plan Calculator](https://configcat.com/calculator/) to calculate your estimated config JSON downloads.
Keep track of the number of config JSON downloads your apps are making on the [Usage & Quota page.](https://app.configcat.com/product/usage)

#### Current config JSON download limits[](#current-config-json-download-limits "Direct link to Current config JSON download limits")
##### Shared infrastructure[](#shared-infrastructure "Direct link to Shared infrastructure")
The following plans run on shared infrastructure. So all customers use the same API nodes and Config Delivery Network (CDN).
| Plan | total req/month | avg. req/sec | max. spike req/s |
| -------------- | --------------- | ------------ | ---------------- |
| **Free** | 5,000,000 | ~2 | ~4 |
| **Pro** | 25,000,000 | ~10 | ~20 |
| **Smart** | 250,000,000 | ~100 | ~200 |
| **Enterprise** | 1,000,000,000 | ~400 | ~800 |
Use the [Plan Calculator](https://configcat.com/calculator/) to get your estimated config JSON downloads.
info
If you reach this limit, we will keep your application up and running. However, you can expect us to contact you on how we can meet your needs.
##### Dedicated infrastructure[](#dedicated-infrastructure "Direct link to Dedicated infrastructure")
The following plans include dedicated API and CDN nodes.
###### Hosted[](#hosted "Direct link to Hosted")
Runs on dedicated infrastructure provided by ConfigCat. The basic package includes:
* 1x API node
* 6x CDN nodes
| | total req/month | avg. req/sec | max. spike req/s |
| ----------------------------- | --------------- | ------------ | ---------------- |
| **Basic package** | 6,000,000,000 | ~2400 | ~4800 |
| **Every additional CDN node** | + 1,000,000,000 | ~400 | ~800 |
###### On-Premise (Self-hosted)[](#on-premise-self-hosted "Direct link to On-Premise (Self-hosted)")
Runs on the customer's own infrastructure. We suggest [contacting ConfigCat's engineering](https://configcat.com/support/) team for exact requirements and performance characteristics.
#### config JSON downloads[](#config-json-downloads "Direct link to config JSON downloads")
The ConfigCat SDK, which you import into your applications, downloads your feature flags and settings in the form of a config JSON file from the ConfigCat CDN and caches it locally.
#### `GetValue()` call is NOT a config JSON download[](#getvalue-call-is-not-a-config-json-download "Direct link to getvalue-call-is-not-a-config-json-download")
Reading feature flag and setting values from cache with `GetValue()` is not considered as a config JSON download. If the cache is empty (e.g., upon application launch) or expired, a config JSON will be downloaded, and all subsequent `GetValue()` calls will then be served from the cache.
#### Example use cases[](#example-use-cases "Direct link to Example use cases")
##### Frontend/mobile/desktop applications[](#frontendmobiledesktop-applications "Direct link to Frontend/mobile/desktop applications")
Typically, you have a high number of frontend/mobile/desktop application instances. Your user count determines this number.
###### Example: A standard web application with 15k active users[](#example-a-standard-web-application-with-15k-active-users "Direct link to Example: A standard web application with 15k active users")
Web apps run in the browser, so for each user, there will be a different ConfigCat SDK instance running. In this example, we have 15,000 active users who usually spend 5 hours on your web application per month. The ConfigCat SDK runs in Auto polling mode with the default 60 seconds polling interval.
> **18,000** *(5 hours in seconds)* / **60** *polling interval* = **300 config JSON downloads/user/month** **15,000** *(users)* × **300** *(config JSON downloads/user/month)* = **4,500,000 config JSON downloads / month**
###### Example: A mobile application running on 5k devices 24/7[](#example-a-mobile-application-running-on-5k-devices-247 "Direct link to Example: A mobile application running on 5k devices 24/7")
Having a mobile app that runs on the devices as a background process. The ConfigCat SDK runs in Auto polling mode with 1 hour polling interval. Your application runs on 5,000 devices.
> **5,000** *(devices)* × **730** *(hours in a month)* = **3,650,000 config JSON downloads / month**
##### Backend applications[](#backend-applications "Direct link to Backend applications")
Backend applications typically have fewer instances than frontend applications.
###### Example: Average frequency polling in 4 instances[](#example-average-frequency-polling-in-4-instances "Direct link to Example: Average frequency polling in 4 instances")
Let's say you have an API for your frontend application, and you have 4 instances of it behind a load balancer. All these 4 instances use the ConfigCat SDK in Auto Polling mode with a 1-minute polling interval.
> **4** *(instances)* × **43,800** *(minutes in a month)* = **175,200 config JSON downloads / month**
###### Example: High frequency polling in 10 instances[](#example-high-frequency-polling-in-10-instances "Direct link to Example: High frequency polling in 10 instances")
Suppose you want your system to react faster after changing a feature flag in ConfigCat. You can decrease the default polling interval all the way down to 1 second. In this case, we are calculating with 10 running instances.
> **10** *(instances)* × **2,592,000** *(seconds in a month)* = **25,920,000 config JSON downloads / month**
#### How to lower the monthly config JSON download count?[](#how-to-lower-the-monthly-config-json-download-count "Direct link to How to lower the monthly config JSON download count?")
##### Use the ConfigCat Client as a Singleton[](#use-the-configcat-client-as-a-singleton "Direct link to Use the ConfigCat Client as a Singleton")
Make sure that you use the *ConfigCat Client* as a Singleton object in your application code. If you want to use multiple SDK Keys in the same application, create only one *ConfigCat Client* per SDK Key.
##### Increase the polling interval[](#increase-the-polling-interval "Direct link to Increase the polling interval")
You can lower the frequency your application downloads the `config JSON` by setting larger polling intervals or using a different [polling mode](https://configcat.com/docs/advanced/caching.md) other than the default auto polling. See the [SDK References for more.](https://configcat.com/docs/sdk-reference/overview.md)
##### Use webhooks[](#use-webhooks "Direct link to Use webhooks")
In a backend application, you may want to consider using [Webhooks.](https://configcat.com/docs/advanced/notifications-webhooks.md) This way your application receives notifications about changes and downloads the `config JSON` only when needed.
##### Call your backend instead of the ConfigCat CDN[](#call-your-backend-instead-of-the-configcat-cdn "Direct link to Call your backend instead of the ConfigCat CDN")
In the case of a frontend application, you can reduce the number of calls made towards the ConfigCat CDN by moving the evaluation logic from the frontend application to your backend.
##### Use the ConfigCat Proxy to cache/proxy config JSON downloads[](#use-the-configcat-proxy-to-cacheproxy-config-json-downloads "Direct link to Use the ConfigCat Proxy to cache/proxy config JSON downloads")
The [ConfigCat Proxy](https://configcat.com/docs/advanced/proxy/proxy-overview.md) allows you to host a feature flag evaluation and config JSON proxy/cache service within your own infrastructure. The [CDN proxy](https://configcat.com/docs/advanced/proxy/endpoints.md#cdn-proxy) feature allows you to proxy/cache config JSON downloads, and the ConfigCat SDKs can be routed to the ConfigCat Proxy running in your own infrastructure, greatly reducing the number of config JSON downloads.
##### Purchase additional config JSON downloads[](#purchase-additional-config-json-downloads "Direct link to Purchase additional config JSON downloads")
If your application requires more config JSON downloads than your current plan includes, you can purchase additional quota as an add-on. You can find the current add-on options [here](https://configcat.com/policies/billing/#pre-purchased-quota).
[Contact us](https://configcat.com/support/) and we will help.
---
## Network Traffic
### Network Traffic
Copy page
Network Traffic refers to the data transmitted between your applications and ConfigCat CDN. It includes the requests made to fetch feature flags and settings.
Generally speaking, the Network Traffic is proportional to:
* the size of the `config JSON`,
* the number of clients connecting to ConfigCat,
* and the frequency of changes in the `config JSON`.
Here are a few examples of config JSON file sizes:
| Config JSON complexity | | Network Traffic | |
| ---------------------- | --------------- | ------------------- | ----------------------------------- |
| # of feature flags | Targeting Rules | first download size | no change `304 - Not Modified` |
| 11 | none | 0.5 kB | 65 B |
| 17 | few | 1.6 kB | 65 B |
| 370 | many | 159 kB | 65 B |
#### Factors affecting Network Traffic[](#factors-affecting-network-traffic "Direct link to Factors affecting Network Traffic")
###### Size of the `config JSON`[](#size-of-the-config-json "Direct link to size-of-the-config-json")
It is affected by the number of feature flags, settings, targeting rules, segments, and the length of their values.
###### Number of clients connecting to ConfigCat[](#number-of-clients-connecting-to-configcat "Direct link to Number of clients connecting to ConfigCat")
Every time a client downloads the config JSON, it contributes to the overall Network Traffic.
###### Frequency of changes in the `config JSON`[](#frequency-of-changes-in-the-config-json "Direct link to frequency-of-changes-in-the-config-json")
The `config JSON` is cached on the ConfigCat CDN. If there is no change, the ConfigCat CDN will respond with `304 Not Modified`. If there is a change, the ConfigCat CDN will respond with `200 OK` and the new `config JSON` content in the response body.
##### Shared infrastructure[](#shared-infrastructure "Direct link to Shared infrastructure")
The following plans run on shared infrastructure. So all customers use the same API nodes and Config Delivery Network (CDN).
| Plan | Data / month |
| -------------- | ------------ |
| **Free** | 20 GB |
| **Pro** | 100 GB |
| **Smart** | 1 TB |
| **Enterprise** | 4 TB |
info
If you hit this limit, we will keep your application up and running. However, you can expect us to contact you on how we can meet your needs.
##### Dedicated infrastructure[](#dedicated-infrastructure "Direct link to Dedicated infrastructure")
The following plans include dedicated API and CDN nodes.
###### Hosted[](#hosted "Direct link to Hosted")
Runs on dedicated servers provided by ConfigCat.
| | Data / month |
| ----------------- | ------------ |
| **Basic package** | 24 TB |
###### On-Premise (Self-hosted)[](#on-premise-self-hosted "Direct link to On-Premise (Self-hosted)")
Runs on the customer's own servers. We suggest [contacting ConfigCat's engineering](https://configcat.com/support/) team on exact requirements and performance.
#### How to reduce the monthly Network Traffic?[](#how-to-reduce-the-monthly-network-traffic "Direct link to How to reduce the monthly Network Traffic?")
##### Delete the old feature flags and unused Targeting Rules[](#delete-the-old-feature-flags-and-unused-targeting-rules "Direct link to Delete the old feature flags and unused Targeting Rules")
If you have a large number of feature flags and Targeting Rules in a config, you can reduce the size of the `config JSON` by deleting the old ones. The [Zombie Flags](https://configcat.com/docs/zombie-flags.md) feature can help you finding stale feature flags.
##### Avoid keeping lots of data in the comparison value of Targeting Rules or segments[](#avoid-keeping-lots-of-data-in-the-comparison-value-of-targeting-rules-or-segments "Direct link to Avoid keeping lots of data in the comparison value of Targeting Rules or segments")
The comparison value of a Targeting Rule or segment is stored in the `config JSON` and downloaded by the SDKs. If you have a lot of Targeting Rules or segments with lengthy comparison values, you can reduce the size of the `config JSON` by shortening them.
##### Consider the amount of text you keep in a text setting's value[](#consider-the-amount-of-text-you-keep-in-a-text-settings-value "Direct link to Consider the amount of text you keep in a text setting's value")
Similarly to the comparison value of Targeting Rules or segments, the value of a text setting is stored in the `config JSON` and downloaded by the SDKs. If you have a lot of text settings with lengthy values, you can reduce the size of the `config JSON` by shortening them.
##### Separate your feature flags into multiple configs[](#separate-your-feature-flags-into-multiple-configs "Direct link to Separate your feature flags into multiple configs")
If you have a large number of feature flags, you can reduce the size of the `config JSON` by separating them into multiple configs. This way, the payload of each download will be smaller.
##### Use the ConfigCat Proxy to cache/proxy config JSON downloads[](#use-the-configcat-proxy-to-cacheproxy-config-json-downloads "Direct link to Use the ConfigCat Proxy to cache/proxy config JSON downloads")
The [ConfigCat Proxy](https://configcat.com/docs/advanced/proxy/proxy-overview.md) allows you to host a feature flag evaluation and config JSON proxy/cache service within your own infrastructure. The [CDN proxy](https://configcat.com/docs/advanced/proxy/endpoints.md#cdn-proxy) feature allows you to proxy/cache config JSON downloads, and the ConfigCat SDKs can be routed to the ConfigCat Proxy running in your own infrastructure greatly reducing network traffic.
##### Purchase additional network traffic[](#purchase-additional-network-traffic "Direct link to Purchase additional network traffic")
If your application requires more network traffic than your current plan includes, you can purchase additional quota as an add-on. You can find the current add-on options [here](https://configcat.com/policies/billing/#pre-purchased-quota).
[Contact us](https://configcat.com/support/) and we will help.
---
## Service Status & Monitoring
### Service Status & Monitoring
Copy page
To check the current health and status of the service visit: .
#### API[](#api "Direct link to API")
Serves the Dashboard with data. Provides an interface for creating and updating Feature Flags. Runs the business logic and keeps CDN Servers consistent with the Database.
#### CDN[](#cdn "Direct link to CDN")
Serving our customers' JSON configuration files containing Feature Flags, Settings and their values. Designed to scale quickly and to handle a massive number of requests.
#### Dashboard[](#dashboard "Direct link to Dashboard")
Graphical user interface (GUI) even for non-technical people to easily manage Configs, Feature Flags and Settings, invite team mates, add/remove Group Permissions or view the Audit Log.
---
## Plans, Purchase & Billing
### Plans, Purchase & Billing
Copy page
#### Plans[](#plans "Direct link to Plans")
ConfigCat is a feature flag service with unlimited team size, awesome support, and a reasonable price tag. You can use ConfigCat by subscribing with an email address which is free forever. Additionally, we offer three more plans with fewer limitations and more additional features. For a detailed comparison [check out the pricing table](https://configcat.com/pricing/).
If you need a comprehensive table of all the business and technical limits of each plan, see the [Subscription Plan Limits Table](https://configcat.com/docs/subscription-plan-limits.md).
##### Shared vs Dedicated infrastructure[](#shared-vs-dedicated-infrastructure "Direct link to Shared vs Dedicated infrastructure")
**Free, Pro, Smart, Enterprise plans** run on shared infrastructure. So all the customers are using the same API and Config Delivery Network.
**Hosted** plan has dedicated API and CDN nodes for their exclusive use, fully separated from the shared infrastructure. Dedicated customers can also drop their nodes to preferred geographic locations.
**On-Premise** plan includes only the distribution of the ConfigCat service via [Docker containers](https://www.docker.com/resources/what-container). So customers can run the service on their own infrastructure.
##### Self-service vs Assisted plans[](#self-service-vs-assisted-plans "Direct link to Self-service vs Assisted plans")
**Free, Pro, Smart plans** are self-service. Using any of those plans should not require manual assistance from the ConfigCat team.
**Enterprise, Hosted, On-Premise plans** include manual assistance from the ConfigCat team like filling forms, providing reports, reviewing contracts or setting up bank transfers.
#### How to purchase a ConfigCat plan?[](#how-to-purchase-a-configcat-plan "Direct link to How to purchase a ConfigCat plan?")
You can purchase a ConfigCat subscription plan on the [Plans page](https://app.configcat.com/plans).
info
You must have a [Billing Manager](https://configcat.com/docs/organization.md) role in your Organization to change or upgrade your plan.
##### Our payment provider[](#our-payment-provider "Direct link to Our payment provider")
If you select to upgrade your current plan, we are taking you to a third party provider called [Chargebee](https://www.chargebee.com/). After completing the purchase, you are taken back to your newly upgraded ConfigCat account.
##### Security[](#security "Direct link to Security")
Credit card information is stored and managed by [Chargebee](https://www.chargebee.com/), our payment provider.
#### How to update billing information?[](#how-to-update-billing-information "Direct link to How to update billing information?")
You can update your billing info on the [Manage Billing page](https://app.configcat.com/organization/billing).
info
You must have a [Billing Manager](https://configcat.com/docs/organization.md) role in your Organization to update your billing info.
---
## Subscription Plan Limits
### Subscription Plan Limits
Copy page
This page lists the limits of the different subscription plans. See the [pricing page](https://configcat.com/pricing) for more information about the plans.
info
Every value marked with a \* in the table marks a technical limit. If you reach a technical limit [contact our support team](https://configcat.com/support/) and we will increase it for you.
| | Free | Pro | Smart | Enterprise | Dedicated | Student | Teacher |
| ----------------------------------------------------------------------------------------------------------------- | ------- | ------- | ------- | ---------- | --------- | ------- | ------- |
| Config JSON downloads (million) | 5 | 25 | 250 | 1000 | 6000 | 25 | 5 |
| Network traffic (per month) | 20GB | 100GB | 1TB | 4TB | 24TB | 100GB | 100GB |
| Products | 2 | 3 | 10 | 1000\* | 1000\* | 3 | 1000 |
| Environments (per product) | 2 | 3 | 50\* | 50\* | 50\* | 3 | 2 |
| Segments (per product) | 2 | 3 | 500\* | 1000\* | 1000\* | 3 | 3 |
| Feature flags / Settings (per product) | 10 | 100 | 500\* | 500\* | 500\* | 1000 | 10 |
| Percentage Options (per feature flag) | 4 | 8 | 500\* | 500\* | 500\* | 8 | 4 |
| Targeting Rules (per feature flag) | 4 | 8 | 500\* | 500\* | 500\* | 8 | 4 |
| Targeting Rule comparison value length (chars) | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 |
| Webhooks (per environment) | 1 | 3 | 200\* | 200\* | 200\* | 3 | 1 |
| Connected integrations (per product, per integration type) e.g. Datadog, Slack, Amplitude, Mixpanel, Segment | 2 | 3 | 100\* | 100\* | 100\* | 3 | 3 |
| Permission groups (per product) | 1 | 2 | 100\* | 100\* | 100\* | 2 | 3 |
| Audit log retention (days) | 7 | 35 | 35 | 750 | 750 | 35 | 7 |
| Verified domains for SAML | 1 | 1 | 1000\* | 1000\* | 1000\* | 1 | 1 |
| Comparison value list length | 100 | 1000 | 15000 | 15000 | 15000 | 1000 | 1000 |
| Comparison value item length | 255 | 255 | 255 | 255 | 255 | 255 | 255 |
| User Provisioning (SCIM) synced users | 10000\* | 10000\* | 10000\* | 10000\* | 10000\* | 10000\* | 10000\* |
| User Provisioning (SCIM) synced groups | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* |
| User Provisioning (SCIM) groups with permissions | 2 | 5 | 10 | 500\* | 500\* | 5\* | 5\* |
| Proxy profiles | 1 | 2 | 10 | 100\* | 100\* | 2\* | 2\* |
| Proxy profile max selected SDK keys | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* | 1000\* |
---
## Organization & Roles
### Organization & Roles
Copy page
An *Organization* represents a collection of preferences that apply to all your *Products* and *Members* in that *Organization*. This includes things like billing information, sign-in methods, and data privacy settings.
The *Manage Organization* menu is only available for *Organization Admins*.

#### Organization Admin role[](#organization-admin-role "Direct link to Organization Admin role")
*Organization Admins* have full access to the entire organization and all products. For example, they can:
* Add or remove members
* Set up security settings
* Change sign-in methods
* Create or delete products, feature flags, and environments
They **do not** have access to billing or subscription settings unless they are also *Billing Managers*.
Only *Organization Admins* can assign or remove the *Organization Admin* role from others.
#### Billing Manager role[](#billing-manager-role "Direct link to Billing Manager role")
Only *Billing Managers* can:
* View and update billing information
* Change the subscription plan
* Assign or remove the *Billing Manager* role from others
*Billing Managers* **cannot** access products, environments, configs, or feature flags, unless they are also *Organization Admins*.
---
## News & Product Updates
### News & Product Updates
Copy page
Here, you'll find all the latest updates, enhancements, and new features we've added to our service. Stay tuned to this page to keep up with all the latest news from ConfigCat!
#### Predefined variations are here\
###### Feb 20, 2026[](#feb-20-2026 "Direct link to Feb 20, 2026")
You asked for a structured way to reuse feature flag values, so we built **predefined variations**.
Instead of typing the same values again and again, define them once. Then select them from a dropdown when you build targeting rules.
Small change. Big difference.
This helps teams:
* Keep values consistent across environments and rules
* Prevent typos and invalid values
* Reuse complex values such as JSON objects
* Add clear labels and hints for teammates
You stay in control.
You can also convert existing flags from free-form values to predefined variations, and back, without breaking your applications in production.
Predefined variations are available in all plans. They extend ConfigCat's powerful targeting capabilities without adding complexity.
Learn more in the [Predefined Variations documentation](https://configcat.com/docs/advanced/predefined-variations.md).

***
#### Feature flag evaluation in GitHub Actions[](#feature-flag-evaluation-in-github-actions "Direct link to Feature flag evaluation in GitHub Actions")
###### Feb 2, 2026[](#feb-2-2026 "Direct link to Feb 2, 2026")
We have released a new GitHub Action that can evaluate feature flags in GitHub workflows.
For more details about how to use the action, [see the documentation](https://configcat.com/docs/integrations/github-eval.md).
***
#### Enhanced SDK key filtering with Proxy Profile selection rules[](#enhanced-sdk-key-filtering-with-proxy-profile-selection-rules "Direct link to Enhanced SDK key filtering with Proxy Profile selection rules")
###### Jan 30, 2026[](#jan-30-2026 "Direct link to Jan 30, 2026")
We're happy to announce that we improved the Proxy Profile's SDK key selection mechanism.
In addition to manual configuration, you can now build custom selection rules that respond to future product, config, and environment creation/deletion/renaming.

For more details about how selection rules work, [see the documentation](https://configcat.com/docs/advanced/proxy/proxy-overview.md#selection-rules).
***
#### New payment currencies (AUD, GBP) available[](#new-payment-currencies-aud-gbp-available "Direct link to New payment currencies (AUD, GBP) available")
###### Jan 27, 2026[](#jan-27-2026 "Direct link to Jan 27, 2026")
You can now pay your ConfigCat subscription in **Australian dollars (AUD)** and **British pounds (GBP)**, in addition to USD and EUR.
To switch from your current payment currency, contact [](mailto:sales@configcat.com). We will help you with the change.
If you prefer another currency, just let us know at [](mailto:sales@configcat.com). We will check what is possible and get back to you.
***
#### More control over your Slack notifications[](#more-control-over-your-slack-notifications "Direct link to More control over your Slack notifications")
###### Jan 19, 2026[](#jan-19-2026 "Direct link to Jan 19, 2026")
Good news! We listened to your feedback and made our Slack integration more flexible.
You can now control whether Slack notifications show or hide sensitive targeting data. This gives more context in private channels, while keeping safe defaults for shared ones.
Until now, comparison values used with confidential (hashed) operators were always masked in Slack. This remains the default behavior.
From now on, you can optionally change this setting for existing Slack integrations on the [Integrations page](https://app.configcat.com/product/integrations). When creating a new Slack integration, you will be asked during setup whether targeting rule values should be sent in cleartext.
No action is required to keep sensitive data hidden for existing integrations. We recommend keeping this setting disabled for shared or public Slack channels.

***
#### ConfigCat MCP Server[](#configcat-mcp-server "Direct link to ConfigCat MCP Server")
###### Sept 30, 2025[](#sept-30-2025 "Direct link to Sept 30, 2025")
We just released a new official ConfigCat's Model Context Protocol (MCP) Server. AI tools like Cursor can now interact with ConfigCat via our new MCP server.
* **Complete set of tools for ConfigCat's Public Management API operations** You can Create, Read, Update and Delete any entities like Feature Flags, Configs, Environments or Products within ConfigCat.
* **Enables your code editor to understand your feature flags** Integrate the appropriate ConfigCat SDK, implement feature flags in your project, remove Zombie (stale) flags and more.
[]()
For more info about how to set up the MCP server, [see Documentation](https://configcat.com/docs/advanced/mcp-server.md).
***
#### Automatic ConfigCat Proxy configuration with Proxy profiles / OpenFeature Remote Evaluation Protocol[](#automatic-configcat-proxy-configuration-with-proxy-profiles--openfeature-remote-evaluation-protocol "Direct link to Automatic ConfigCat Proxy configuration with Proxy profiles / OpenFeature Remote Evaluation Protocol")
###### Aug 22, 2025[](#aug-22-2025 "Direct link to Aug 22, 2025")
We have two exciting [ConfigCat Proxy](https://configcat.com/docs/advanced/proxy/proxy-overview.md) related news:
1. From the [v2.0.0](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0) version, the Proxy has the ability to use [Proxy profiles](https://app.configcat.com/organization/proxy-profiles) to determine which SDK keys to download and distribute.
info
You need to be an Organization Admin to access the Proxy profiles page on the Dashboard.

[See the documentation](https://configcat.com/docs/advanced/proxy/proxy-overview.md#1-automatic-configuration-with-proxy-profiles) for more information on how to set up your Proxy with profiles.
2. From the [v2.0.0](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0) version, the Proxy conforms to the [OpenFeature Remote Evaluation Protocol](https://github.com/open-feature/protocol) (OFREP), which means it can be used with OFREP compatible OpenFeature providers. [See the API documentation](https://configcat.com/docs/advanced/proxy/endpoints.md#openfeature-remote-evaluation-protocol-ofrep) for the OFREP implementation with usage examples.
***
#### New SDK for JavaScript with Cloudflare Workers support[](#new-sdk-for-javascript-with-cloudflare-workers-support "Direct link to New SDK for JavaScript with Cloudflare Workers support")
###### Aug 15, 2025[](#aug-15-2025 "Direct link to Aug 15, 2025")
We just released the [new, revamped ConfigCat SDK for JavaScript platforms](https://configcat.com/docs/sdk-reference/js/overview/). Unlike the previous platform-specific SDKs, it ships as a [single, unified NPM package](https://www.npmjs.com/package/@configcat/sdk) that supports multiple JS environments.

The new SDK combines and, thus, supersedes these SDKs:
* [ConfigCat SDK for JavaScript frontend applications](https://configcat.com/docs/sdk-reference/js/)
* [ConfigCat SDK for JavaScript Server-Side Rendered applications](https://configcat.com/docs/sdk-reference/js-ssr/)
* [ConfigCat SDK for Node.js](https://configcat.com/docs/sdk-reference/node/)
* [ConfigCat SDK for Chromium Extensions](https://github.com/configcat/js-chromium-extension-sdk)
The legacy SDKs remain available for use but won't receive new features and improvements any more. They will continue getting security updates until official support ends on August 31, 2026.
The new SDK maintains strong backward compatibility, so in most cases migration is simple and straightforward. For details, see the "Migration to the new SDK" section in the SDK references linked above.
But there are other advantages to upgrading to the new SDK sooner rather than later:
* Most notably, it adds support for **Deno**, **Bun** and **Cloudflare Workers**. Plus, makes the Browser and Chromium Extension SDKs work in **Web Workers** too.
* Another improvement worth mentioning is that the new SDK is a **zero-dependency library**, which can spare you some package management-related headaches. It distributes **ES2017-compatible code** to allow you to minimize the library's footprint in your application bundles.
* A nice new feature is **query string-based flag overrides** (especially handy during development) and the possibility of **custom flag override data sources** - even with full feature flags, not just simple values (useful for testing).
* Then there is a **new hook** named `configFetched` for observing config fetch errors and **new options** named `configFetcher` and `logFilter` for customizing config fetching and logging.
* Error reporting received nice improvements as well: among others, the SDK now includes **error codes** to help identify error causes.
For the full list of new features and improvements, take a look at the [release notes](https://github.com/configcat/js-unified-sdk/releases/tag/v1.0.0).
***
#### New ConfigCat OpenFeature providers[](#new-configcat-openfeature-providers "Direct link to New ConfigCat OpenFeature providers")
###### July 4, 2025[](#july-4-2025 "Direct link to July 4, 2025")
We're happy to share that we have released new OpenFeature providers for the following platforms:
* [Angular](https://configcat.com/docs/sdk-reference/openfeature/angular.md)
* [React](https://configcat.com/docs/sdk-reference/openfeature/react.md)
* [NestJS](https://configcat.com/docs/sdk-reference/openfeature/nestjs.md)
* [Swift (iOS)](https://configcat.com/docs/sdk-reference/openfeature/swift.md)
* [Kotlin (Android)](https://configcat.com/docs/sdk-reference/openfeature/kotlin.md)
* [Ruby](https://configcat.com/docs/sdk-reference/openfeature/ruby.md)
[See the documentation](https://configcat.com/docs/sdk-reference/openfeature.md) for the complete list of currently supported platforms.
***
#### Quality of Life improvements[](#quality-of-life-improvements "Direct link to Quality of Life improvements")
###### Jun 3, 2025[](#jun-3-2025 "Direct link to Jun 3, 2025")
We've just rolled out a set of updates that make working with feature flags in ConfigCat smoother and more practical. Here's what's new:
##### Zombie flag Report improvements[](#zombie-flag-report-improvements "Direct link to Zombie flag Report improvements")
Stale feature flags can build up quickly and lead to technical debt. We've improved the Zombie Flags feature to make it more useful and easier to manage:
* **New Zombie Flags page** The original email report didn't offer immediate feedback. That's why we created the new [Zombie Flags page](https://app.configcat.com/product/zombie-flags), where you can instantly view stale flags and filter them by product. If you're using our [Code References](https://configcat.com/docs/advanced/code-references/overview.md) feature, the page also shows exactly where the flags appear in your code, making it easier to clean things up.
* **Ignore flags by tag** If you have long-lived feature flags that are meant to stay, you can now tag them (for example, with “permanent”) and exclude them from the Zombie Flags Report.
* **Less noise, more focus** The previous report included any flag that was stale in at least one selected environment. Now, you can adjust the settings so only flags that are stale in all selected environments appear in the report.
* **Now available via API** You can also check stale flags programmatically using the [Zombie (stale) flags](https://configcat.com/docs/api/reference/get-staleflags.md) endpoint in our Public Management API.
Narrow down your [Zombie Flags Report](https://app.configcat.com/my-account/zombie-flags-report) email with the new preferences, try out our new [Zombie Flags page](https://app.configcat.com/product/zombie-flags), or check the [documentation](https://configcat.com/docs/zombie-flags.md) to learn more.

##### Clone feature flag[](#clone-feature-flag "Direct link to Clone feature flag")
Cloning a feature flag now lets you quickly create a new flag in any config. It copies over all the targeting rules, values across environments, and tags, making setup faster and more consistent.

##### Copy all feature flag rules[](#copy-all-feature-flag-rules "Direct link to Copy all feature flag rules")
We've made it easier to copy flag values across environments. Now, you can:
* Copy rules for an entire config, or
* Choose specific feature flags to copy.

##### A Smoother Flag Creation Experience[](#a-smoother-flag-creation-experience "Direct link to A Smoother Flag Creation Experience")
When creating a new feature flag, you no longer have to set values separately for each environment. You can now set them once globally, then fine-tune as needed later.
We truly hope you'll love these new features and improvements. Happy feature flagging! ❤️
***
#### 🚀 Refer & Earn with ConfigCat[](#-refer--earn-with-configcat "Direct link to 🚀 Refer & Earn with ConfigCat")
###### May 30, 2025[](#may-30-2025 "Direct link to May 30, 2025")
Earn up to **$10,000 per referral** just by sharing something you already love.
##### Here’s how it works:[](#heres-how-it-works "Direct link to Here’s how it works:")
* 👥 The people you refer get **10% off** any paid plan.
* 💰 You earn **20% of their payments**, up to **$10,000 per referral**.
* 💸 Get paid via **PayPal** (more payout options coming soon).
* 🔗 Share your unique referral link via **email, LinkedIn, or QR code** – powered by [Cello](https://cello.so/).


> This isn’t just a referral program - it’s our way of saying *thank you* for being part of the ConfigCat community. You help us grow, and we make sure you benefit too.
✅ No cold outreach. No contact sharing. You're simply sharing something you already use and like.
**Ready to start earning?** Click the **“Refer & Earn”** button in your ConfigCat dashboard and let the rewards roll in.
***
#### User provisioning (SCIM) is here\ is here!")
###### May 21, 2025[](#may-21-2025 "Direct link to May 21, 2025")
**We're happy to announce that ConfigCat now supports user provisioning using SCIM (System for Cross-domain Identity Management)!**
SCIM makes it easy to sync users and groups from your Identity Provider into your ConfigCat Organization. Once synced, you can link Identity Provider groups to ConfigCat permission groups, so users are placed in the right roles without manual work.
We've tested the feature with [Entra ID (Azure AD)](https://configcat.com/docs/advanced/team-management/scim/identity-providers/entra-id.md), [Okta](https://configcat.com/docs/advanced/team-management/scim/identity-providers/okta.md) and [OneLogin](https://configcat.com/docs/advanced/team-management/scim/identity-providers/onelogin.md), but any Identity Provider that supports the SCIM 2.0 protocol should work too.
SCIM provisioning is available on all ConfigCat plans, including the Free plan. Each plan includes limits for synced users, groups, and permission assignments. See details [here](https://configcat.com/docs/subscription-plan-limits.md).
Read our [documentation](https://configcat.com/docs/advanced/team-management/scim/scim-overview.md) and set up the User provisioning on the [Authentication & Provisioning](https://app.configcat.com/organization/authentication) page in your ConfigCat Dashboard.
info
You'll need to be an Organization Admin to access it.


***
#### Import from LaunchDarkly is here\
###### Apr 29, 2025[](#apr-29-2025 "Direct link to Apr 29, 2025")
**Thinking about moving away from LaunchDarkly? ConfigCat just made that easier for you.**
If you're curious about switching to a LaunchDarkly alternative, ConfigCat has good news for you: we've launched a new feature called the "Import from LaunchDarkly" tool, which makes it a breeze to migrate LaunchDarkly feature flags and segments into ConfigCat.
It's available on all plans, even the Free plan. So if you're just exploring, you can give it a go with zero commitment. (Just a heads-up: your plan's limits still apply. If you bump into anything, [contact us](https://configcat.com/support/?prefilled=ld-import-limit), and we'll surely figure out a solution for you!)
You can find the import tool on the [Organization Overview](https://app.configcat.com/organization) page in your ConfigCat Dashboard:

info
You'll need to be an Organization Admin to access it.
If you decide to make the full switch, we've prepared a [migration guide](https://configcat.com/docs/advanced/migration-from-launchdarkly.md) to walk you through the whole process.
So why not make the jump? You'll land on your paws anyway. 🐱
***
#### Price Adjustment & Smart Plan Update[](#price-adjustment--smart-plan-update "Direct link to Price Adjustment & Smart Plan Update")
###### Feb 17, 2025[](#feb-17-2025 "Direct link to Feb 17, 2025")
As of 17th February 2025, we've made the following updates:
##### Price adjustment[](#price-adjustment "Direct link to Price adjustment")
Due to changes in the EUR-USD exchange rate, we've made an adjustment to our prices:
* Our EUR plans will have a 10% increase
* Our USD plans will have a 1% increase
This applies only to new upgrades and future customers.
##### Smart plan Update[](#smart-plan-update "Direct link to Smart plan Update")
* The Smart Plan now has a product limit of 10.
Existing Smart plan customers are not affected by this change.
***
#### What's new in 2025[](#whats-new-in-2025 "Direct link to What's new in 2025")
###### Jan 20, 2025[](#jan-20-2025 "Direct link to Jan 20, 2025")
We have a few important updates to share with you, including new integrations, changes to our pricing, and some highly requested features. Here's what's happening:
##### 🚀 ConfigCat now available in JetBrains Marketplace[](#-configcat-now-available-in-jetbrains-marketplace "Direct link to 🚀 ConfigCat now available in JetBrains Marketplace")
We're happy to announce that the ConfigCat Feature Flag plugin is now available on the JetBrains Marketplace. You can now manage your feature flags directly from 15 supported JetBrains IDEs. Check out the plugin [here](https://configcat.com/docs/integrations/intellij/).
##### 🌓 Dark Mode & UI Facelift[](#-dark-mode--ui-facelift "Direct link to 🌓 Dark Mode & UI Facelift")
Dark Mode has been one of the most requested features, and we're happy to announce that it's now available! Plus, we've given the UI a fresh, modern look to make things even easier and more enjoyable to use.

##### 💳 Multiple Payment Sources[](#-multiple-payment-sources "Direct link to 💳 Multiple Payment Sources")
You can now add backup credit cards to your organization, making your payments more flexible and secure.
##### 📈 Price adjustments and Plan updates[](#-price-adjustments-and-plan-updates "Direct link to 📈 Price adjustments and Plan updates")
We're making a few changes to our pricing plans, which will take effect on 17th February 2025.
* *Price adjustment* Over the past few years, the constantly fluctuating USD/EUR exchange rate has significantly widened the gap between our EUR and USD pricing. We're making adjustments to bring these prices closer together:
* Our EUR plans will have a 10% increase
* Our USD plans will have a 1% increase This change will only apply to upgrades and will affect future customers starting on the 17th February 2025.
* *Updates to Free and Smart plans*
* Free Plan: The Product limit has been increased to 2. Existing Free plan users have automatically received this benefit.
* Smart Plan (effective from 17 February 2025): The Product limit will be capped at 10. Existing Smart plan customers will not be affected by this change.
***
#### Disable two-factor authentication permission[](#disable-two-factor-authentication-permission "Direct link to Disable two-factor authentication permission")
###### Oct 8, 2024[](#oct-8-2024 "Direct link to Oct 8, 2024")
You can disable two-factor authentication for your team members. This feature is useful if someone loses the device used for two-factor authentication.
*Only team members with Organization Admin role or with 'Can disable two-factor authentication for other team members' permission can disable two-factor authentication.*
[Open Team Members page on our Dashboard](https://app.configcat.com/product/members)
***
#### Introducing ConfigCat Playground: Test Feature Flags Easily in a safe environment[](#introducing-configcat-playground-test-feature-flags-easily-in-a-safe-environment "Direct link to Introducing ConfigCat Playground: Test Feature Flags Easily in a safe environment")
###### Sept 26, 2024[](#sept-26-2024 "Direct link to Sept 26, 2024")
We've just released the ConfigCat Playground, a simulator that provides a safe virtual environment where you can try out everything ConfigCat has to offer.
This new feature gives you virtual devices and a virtual app that can be connected to your ConfigCat feature flags. This lets you test feature flags and targeting rules without needing to connect any real applications.
Please do not use the Playground with feature flags already connected to live applications. We highly recommend using feature flags from non-production environments when experimenting in the Playground.
To get started, simply click on the **"Test in Playground"** option in the **...** menu of any boolean feature flag inside your ConfigCat Dashboard.
 
***
#### New ConfigCat OpenFeature providers[](#new-configcat-openfeature-providers-1 "Direct link to New ConfigCat OpenFeature providers")
###### Sept 6, 2024[](#sept-6-2024 "Direct link to Sept 6, 2024")
We're happy to share that we have released new OpenFeature providers for the following platforms:
* [PHP](https://configcat.com/docs/sdk-reference/openfeature/php.md)
* [Python](https://configcat.com/docs/sdk-reference/openfeature/python.md)
* [Rust](https://configcat.com/docs/sdk-reference/openfeature/rust.md)
[See the documentation](https://configcat.com/docs/sdk-reference/openfeature.md) for the complete list of currently supported platforms.
***
#### Integration management via Public Management API and Terraform[](#integration-management-via-public-management-api-and-terraform "Direct link to Integration management via Public Management API and Terraform")
###### Aug 13, 2024[](#aug-13-2024 "Direct link to Aug 13, 2024")
From now on, you can manage your Integrations through the ConfigCat Public Management API and Terraform provider. See the docs for details:
* ConfigCat Public Management API: use the [Integrations](https://api.configcat.com/docs/index.html#tag/Integrations) endpoints.
* ConfigCat Feature Flags Provider for Terraform: use the [configcat\_integration ](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/integration)resource.
***
#### New ConfigCat SDK for Unreal Engine[](#new-configcat-sdk-for-unreal-engine "Direct link to New ConfigCat SDK for Unreal Engine")
###### Jul 31, 2024[](#jul-31-2024 "Direct link to Jul 31, 2024")
We just released a new official ConfigCat SDK supporting Unreal Engine applications.

[See Documentation](https://configcat.com/docs/sdk-reference/unreal.md)
***
#### New ConfigCat SDK for Rust[](#new-configcat-sdk-for-rust "Direct link to New ConfigCat SDK for Rust")
###### Jul 19, 2024[](#jul-19-2024 "Direct link to Jul 19, 2024")
We just released a new official ConfigCat SDK supporting Rust applications.
[See Documentation](https://configcat.com/docs/sdk-reference/rust.md)
***
#### Ability to connect multiple integrations[](#ability-to-connect-multiple-integrations "Direct link to Ability to connect multiple integrations")
###### Jun 27, 2024[](#jun-27-2024 "Direct link to Jun 27, 2024")
We're happy to share that we have added the ability to connect multiple [integrations](https://app.configcat.com/integrations) of the same type. Moreover, it's now possible to apply environment/config filters on each individual integration.
 
***
#### Advanced feature flag analytics with Twilio Segment[](#advanced-feature-flag-analytics-with-twilio-segment "Direct link to Advanced feature flag analytics with Twilio Segment")
###### Jun 14, 2024[](#jun-14-2024 "Direct link to Jun 14, 2024")
We're happy to share that we have introduced a new way to track your feature flags in your analytics tools. From now on you can [send feature flag change events and](https://configcat.com/docs/integrations/segment.md#changeevents) and [send feature flag evaluation analytics](https://configcat.com/docs/integrations/segment.md#analytics) to Twilio Segment.
***
#### Introducing the ConfigCat Feature Flags Tutorial[](#introducing-the-configcat-feature-flags-tutorial "Direct link to Introducing the ConfigCat Feature Flags Tutorial")
###### Jun 11, 2024[](#jun-11-2024 "Direct link to Jun 11, 2024")
We're excited to launch our [Feature Flags Tutorial](https://tutorial.configcat.com/?lm=13), a comprehensive guide designed to enhance your skills in feature management. This tutorial covers everything from basic toggling and simple targeting to advanced techniques like percentage rollouts and handling rollbacks.

##### Tutorial Highlights:[](#tutorial-highlights "Direct link to Tutorial Highlights:")
* Begin with toggling a feature flag on and off to see its immediate impact on a user interface, simulating real-world user scenarios.
* Simple Targeting: Learn to apply basic targeting rules by enabling a feature for all users except those in a specific country.
* Dogfooding: Practice internal testing by setting the feature to be visible only to users from your company.
* Percentage Rollout: Advance to partial feature deployment by enabling a new feature for a percentage of your users, testing its acceptance incrementally.
* Rollback: Master the ability to quickly revert changes for specific user groups when encountering issues during rollout.
This step-by-step guide is ideal for anyone looking to integrate feature flags into their projects efficiently.
[Explore the Tutorial](https://tutorial.configcat.com/?lm=14)
***
#### Advanced feature flag analytics with Mixpanel, Amplitude and Google Analytics[](#advanced-feature-flag-analytics-with-mixpanel-amplitude-and-google-analytics "Direct link to Advanced feature flag analytics with Mixpanel, Amplitude and Google Analytics")
###### May 15, 2024[](#may-15-2024 "Direct link to May 15, 2024")
We're happy to share that we have introduced new ways to track your feature flags in your analytics tools.
From now on you can:
* [Monitor feature flag change events in Mixpanel with Annotations](https://configcat.com/docs/integrations/mixpanel/#annotations)
* [Send feature flag evaluation analytics to Mixpanel Experiments](https://configcat.com/docs/integrations/mixpanel/#experiments)
* [Send feature flag evaluation analytics to Amplitude Experiments](https://configcat.com/docs/integrations/amplitude/#experiments)
* [Send feature flag evaluation analytics to Google Analytics](https://configcat.com/docs/integrations/google-analytics)
***
#### Webhook and Product preference management in Public Management API and Terraform[](#webhook-and-product-preference-management-in-public-management-api-and-terraform "Direct link to Webhook and Product preference management in Public Management API and Terraform")
###### May 8, 2024[](#may-8-2024 "Direct link to May 8, 2024")
From now on, you can manage your Webhooks and Product preferences through the ConfigCat Public Management API and the Terraform provider. See the docs for details:
* ConfigCat Public Management API: use the [Webhooks ](https://api.configcat.com/docs/index.html#tag/Webhooks), [Get Product Preferences](https://api.configcat.com/docs/index.html#tag/Products/operation/get-product-preferences) and [Update Product Preferences](https://api.configcat.com/docs/index.html#tag/Products/operation/update-product-preferences) endpoints.
* ConfigCat Feature Flags Provider for Terraform: use the [configcat\_webhook ](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/webhook)and [configcat\_product\_preferences](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/product_preferences) resources.
***
#### ConfigCat Proxy Released\
###### Apr 17, 2024[](#apr-17-2024 "Direct link to Apr 17, 2024")
We're happy to announce the official release of [ConfigCat Proxy](https://github.com/configcat/configcat-proxy). 🎉
ConfigCat Proxy allows you to host feature flag evaluation service in your own infrastructure. The Proxy provides the following:
🚀 **Performance**: Faster evaluation for stateless or short-lived apps. 🦾 **Reliability**: Continuous operation, even if ConfigCat CDN is down. 🔐 **Security**: Protect config JSON files from exposure to frontend and mobile apps. 📈 **Scalability**: Easily handle varying application loads. 📡 **Streaming**: Real-time feature flag change notifications via SSE and gRPC.
Learn more about ConfigCat Proxy [here](https://configcat.com/docs/advanced/proxy/proxy-overview/).
***
#### Introducing Config V2: More Powerful Feature Flagging\
###### Apr 05, 2024[](#apr-05-2024 "Direct link to Apr 05, 2024")
We're thrilled to announce the upcoming launch of Config V2, the next generation of ConfigCat. This major update introduces a number of enhancements including a revamped Dashboard, Public Management API, updated SDKs, and a host of new features designed to streamline your feature flag and configuration management experience.
##### What's New in Config V2?[](#whats-new-in-config-v2 "Direct link to What's New in Config V2?")
* A modernized config editor UI for an enhanced Dashboard experience.
* Advanced targeting rules with AND conditions for more precise user targeting.
* New comparators and prerequisite flags for complex rule creation.
##### Gradual Release & Opt-in[](#gradual-release--opt-in "Direct link to Gradual Release & Opt-in")
Config V2 will be rolled out gradually over the next three months. Interested customers are encouraged to opt-in early by [contacting our support team](https://configcat.com/support/)
##### Seamless Migration, No Immediate Changes Required[](#seamless-migration-no-immediate-changes-required "Direct link to Seamless Migration, No Immediate Changes Required")
Post-release, rest assured that your existing configurations will continue to function just as before. There's no immediate pressure to migrate, allowing you to transition to Config V2 when it suits you best.
Here is a [detailed guide](https://configcat.com/docs/advanced/config-v2/) to know more about Config V2 and the new features.
***
#### ConfigCat customer experience survey[](#configcat-customer-experience-survey "Direct link to ConfigCat customer experience survey")
###### Mar 22, 2024[](#mar-22-2024 "Direct link to Mar 22, 2024")
Please take a moment to share your experience with ConfigCat. Fill out [this survey](https://forms.gle/VepSDp3pF9FCVzAE9) and help us improve our product! Thank you for your time! 🙏
***
#### Join the Config V2 Beta Program[](#join-the-config-v2-beta-program "Direct link to Join the Config V2 Beta Program")
###### Jan 19, 2024[](#jan-19-2024 "Direct link to Jan 19, 2024")
We're looking for ConfigCat users willing to participate in the beta testing of Config V2.
##### What is Config V2?[](#what-is-config-v2 "Direct link to What is Config V2?")
Config V2 is a new version of ConfigCat. It brings together a bundle of highly requested features like AND conditions, new comparators (Text Equals, Text Starts with Any of, Text Ends with Any of, Before/After), Prerequisite flags, and more. [Read more about Config V2 and the new features.](https://configcat.com/docs/advanced/config-v2.md)
You can get early access to the new features and shape the final product with your feedback.
##### How to join the beta program?[](#how-to-join-the-beta-program "Direct link to How to join the beta program?")
1. [Apply via this form](https://forms.gle/wEFxKYs5Lv5iiLUF8)
2. Join the **#config-v2-beta-testing** channel in our [Community Slack](https://configcat.com/slack/) to give feedback.
***
#### Resource ordering in Public Management API and Terraform[](#resource-ordering-in-public-management-api-and-terraform "Direct link to Resource ordering in Public Management API and Terraform")
###### Jan 9, 2024[](#jan-9-2024 "Direct link to Jan 9, 2024")
From now on, you can change the order of your products, configs and environments trough the ConfigCat Public Management API and the Terraform provider. See the docs for details:
* *ConfigCat Public Management API*: specify the order argument in the [Products](https://configcat.com/docs/api/reference/products.md), [Configs](https://configcat.com/docs/api/reference/configs.md), [Environment](https://configcat.com/docs/api/reference/environments.md) and [Feature Flags & Settings](https://configcat.com/docs/api/reference/feature-flags-settings.md) endpoints
* *ConfigCat Feature Flags Provider for Terraform*: specify the order argument of the [configcat\_product](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/product#argument-reference), [configcat\_config](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/config#argument-reference), [configcat\_environment](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/environment#argument-reference) and [configcat\_setting](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/setting#argument-reference).
***
#### ConfigCat OpenFeature Providers available[](#configcat-openfeature-providers-available "Direct link to ConfigCat OpenFeature Providers available")
###### Jan 5, 2024[](#jan-5-2024 "Direct link to Jan 5, 2024")
OpenFeature now supports ConfigCat via dedicated providers for their SDKs. So if you prefer using ConfigCat via the OpenFeature API, you can now do so with the following providers:
* [ConfigCat OpenFeature Provider for Java](https://github.com/open-feature/java-sdk-contrib/tree/main/providers/configcat)
* [ConfigCat OpenFeature Provider for Go](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/configcat)
* [ConfigCat OpenFeature Provider for JavaScript](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/config-cat)
***
#### ConfigCat Proxy Beta[](#configcat-proxy-beta "Direct link to ConfigCat Proxy Beta")
###### Nov 17, 2023[](#nov-17-2023 "Direct link to Nov 17, 2023")
We're happy to share that the ConfigCat Proxy is now in the Beta phase and we need your help to make it even better!
📚 Want to learn more about the ConfigCat Proxy? Get all the details [here](https://configcat.com/docs/advanced/proxy/proxy-overview.md).
🔧 We'd like to invite you to participate in the beta testing. If you're interested, join the dedicated **#configcat-proxy-beta** channel in our [Slack Community](https://configcat.com/slack). Share your experiences, ask questions, and collaborate with our team and fellow community members.
***
#### New cleartext comparators in Segments[](#new-cleartext-comparators-in-segments "Direct link to New cleartext comparators in Segments")
###### Oct 26, 2023[](#oct-26-2023 "Direct link to Oct 26, 2023")
ConfigCat now supports two new cleartext comparators: IS ONE OF and IS NOT ONE OF.

These new comparators allow you to check if a given value is part of a list or not. This is in addition to the hashed confidential versions that were previously available.
***
#### Unique tag names[](#unique-tag-names "Direct link to Unique tag names")
###### Oct 4, 2023[](#oct-4-2023 "Direct link to Oct 4, 2023")
Now, tag names within a product must be unique. This new feature ensures better organization and avoids any potential confusion with colliding tag names.
***
#### Manage Permission Groups with Terraform[](#manage-permission-groups-with-terraform "Direct link to Manage Permission Groups with Terraform")
###### Aug 23, 2023[](#aug-23-2023 "Direct link to Aug 23, 2023")
Introducing Permission Group management in [**ConfigCat Feature Flags Provider for Terraform**](https://registry.terraform.io/providers/configcat/configcat/latest/docs)! Use the [**configcat\_permission\_group**](https://registry.terraform.io/providers/configcat/configcat/latest/docs/resources/permission_group) resource for control and the [**configcat\_permission\_groups**](https://registry.terraform.io/providers/configcat/configcat/latest/docs/data-sources/permission_groups) data source for access to existing Permission Groups.
***
#### Some updates regarding SLA guaranteed Uptime[](#some-updates-regarding-sla-guaranteed-uptime "Direct link to Some updates regarding SLA guaranteed Uptime")
###### Aug 15, 2023[](#aug-15-2023 "Direct link to Aug 15, 2023")
We're excited to announce important updates to our Service Level Agreement (SLA) concerning uptime commitments.
We're increasing our uptime commitment for the following plans:
| Uptime Changes | Previous | Current |
| --------------- | -------- | --------------- |
| Free Plan | 99% | 99% (No Change) |
| Pro Plan | 99.8% | 99.9% |
| Smart Plan | 99.9% | 99.95% |
| Enterprise Plan | 99.9% | 99.99% |
| Dedicated Plan | 99.9% | 99.99% |
By enhancing our SLA terms, we aim to provide a more consistent and trustworthy service that you can depend on, day in and day out.
***
#### Old SDKs will stop working after October 1st, 2023[](#old-sdks-will-stop-working-after-october-1st-2023 "Direct link to Old SDKs will stop working after October 1st, 2023")
###### Aug 10, 2023[](#aug-10-2023 "Direct link to Aug 10, 2023")
All ConfigCat SDKs released before Feb, 2020 will stop working after October 1st, 2023. Please, upgrade all your SDKs to the latest.
Although we aim to keep older SDK versions functional, those trailing more than one major or minor release lack official support and SLA. Many of these outdated SDKs will no longer remain functional.
##### Affected SDKs and versions[](#affected-sdks-and-versions "Direct link to Affected SDKs and versions")
| SDK Type | Latest available version | Will stop working |
| -------- | ------------------------ | ----------------- |
| Python | v8.0.0 | < v3.0.2 |
| Ruby | v7.0.0 | < v2.0.3 |
| .NET | v8.2.0 | < v4.0.0 |
| Go | v8.0.0 | < v4.0.0 |
| Java | v8.2.2 | < v4.0.0 |
| Android | v9.0.1 | < v4.0.0 |
| JS | v8.1.0 | < v3.0.0 |
| JS-SSR | v7.1.0 | < v1.0.2 |
| Node | v10.1.0 | < v4.0.0 |
| PHP | v7.1.1 | < v3.0.2 |
| Swift | v9.4.0 | < v4.0.0 |
***
#### Introducing Network Traffic limits for all plans[](#introducing-network-traffic-limits-for-all-plans "Direct link to Introducing Network Traffic limits for all plans")
###### Aug 1, 2023[](#aug-1-2023 "Direct link to Aug 1, 2023")
We are introducing [**Network Traffic**](https://configcat.com/docs/network-traffic.md) limits for all plans. The usage is based on the Network Traffic your applications are making to the ConfigCat CDN.
##### Why are we introducing these limits?[](#why-are-we-introducing-these-limits "Direct link to Why are we introducing these limits?")
Our cloud provider charges us for the Network Traffic we use to serve your feature flags. By introducing these limits, we can cover these costs and continue providing the service. Instead of raising prices for all users in general, we decided to specifically reflect the network-related operation costs in our current pricing plans.
##### What are the limits?[](#what-are-the-limits "Direct link to What are the limits?")
| Free | Pro | Smart | Enterprise |
| ---------- | ----------- | --------- | ---------- |
| 20 GB / mo | 100 GB / mo | 1 TB / mo | 4 TB / mo |
##### What to expect?[](#what-to-expect "Direct link to What to expect?")
94% of our users will not be affected by these limits. If you are in the 6% that exceeds the limit, we will reach out to you directly to assist in the next 3 months in finding the best solution for your specific use case. Rest assured that even if you exceed the limit, your feature flags will continue to work seamlessly.
If you have any further questions or need assistance, please don't hesitate to [**reach out to us**](https://configcat.com/support). We're here to help!
***
#### Introducing "Test with User"[](#introducing-test-with-user "Direct link to Introducing \"Test with User\"")
###### Jul 26, 2023[](#jul-26-2023 "Direct link to Jul 26, 2023")
We're pleased to announce the arrival of "Test with User" for feature flags!
With "Test with User," you can now test your feature flags before deploying them to production. Wondering how your flags will perform for specific users? This feature allows you to see the evaluation results based on a given User Object.
***
#### Chromium Extension SDK (Beta)[](#chromium-extension-sdk-beta "Direct link to Chromium Extension SDK (Beta)")
###### Dec 3, 2022[](#dec-3-2022 "Direct link to Dec 3, 2022")
A new JS SDK for Chromium Extensions supporting the [Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/) API is now on public beta and available via [npm](https://www.npmjs.com/package/configcat-js-chromium-extension).
[Open on GitHub](https://github.com/configcat/js-chromium-extension-sdk)
***
#### New ConfigCat SDK for C++[](#new-configcat-sdk-for-c "Direct link to New ConfigCat SDK for C++")
###### Oct 7, 2022[](#oct-7-2022 "Direct link to Oct 7, 2022")
We just released a new official ConfigCat SDK supporting C++ applications.
[See Documentation](https://configcat.com/docs/sdk-reference/cpp.md)
***
#### New ConfigCat SDK for React[](#new-configcat-sdk-for-react "Direct link to New ConfigCat SDK for React")
###### Sept 6, 2022[](#sept-6-2022 "Direct link to Sept 6, 2022")
We just released a new official ConfigCat SDK supporting React applications.
[See Documentation](https://configcat.com/docs/sdk-reference/react.md)
***
#### monday.com integration[](#mondaycom-integration "Direct link to monday.com integration")
###### Jul 18, 2022[](#jul-18-2022 "Direct link to Jul 18, 2022")
Turn your features On / Off right from a monday.com item.
[ConfigCat Feature Flags monday.com app](https://monday.com/marketplace/10000079)
***
#### ISO/IEC 27001:2013 certification[](#isoiec-270012013-certification "Direct link to ISO/IEC 27001:2013 certification")
###### Jun 27, 2022[](#jun-27-2022 "Direct link to Jun 27, 2022")
We're happy to announce that ConfigCat has achieved the ISO/IEC 27001:2013 certification for Information Security Management Systems (ISMS).
[Read more and download the certificates here](https://configcat.com/iso/)
***
#### Reordering feature flags and other entities[](#reordering-feature-flags-and-other-entities "Direct link to Reordering feature flags and other entities")
###### Mar 22, 2022[](#mar-22-2022 "Direct link to Mar 22, 2022")
Click the Reorder icon on any overview to change the ordering of your feature flags, environments, configs or products.
***
#### Copy feature flag values between environments[](#copy-feature-flag-values-between-environments "Direct link to Copy feature flag values between environments")
###### Feb 23, 2022[](#feb-23-2022 "Direct link to Feb 23, 2022")
You can copy feature flag values (including segment, targeting, percentage rules) from one environment to another.
***
#### Segments are here[](#segments-are-here "Direct link to Segments are here")
###### Feb 15, 2022[](#feb-15-2022 "Direct link to Feb 15, 2022")
Segments let you group your users based on any of their properties (e.g: Beta Testers). You can target the same segment with multiple feature flags.
[Go to segments on our Dashboard](https://app.configcat.com/product/segments)
***
#### TV Mode[](#tv-mode "Direct link to TV Mode")
###### Dec 15, 2021[](#dec-15-2021 "Direct link to Dec 15, 2021")
Display your feature flags on the TVs around the office!
[Config overview on our Dashboard](https://app.configcat.com/overview)
***
#### Config Overview[](#config-overview "Direct link to Config Overview")
###### Nov 17, 2021[](#nov-17-2021 "Direct link to Nov 17, 2021")
Introducing a new overview to track your feature flag values in all your environments side-by-side.
Open the environment menu to access the overview.
[Open config overview on our Dashboard](https://app.configcat.com/overview)
***
#### "Which projects are using this flag?"[](#which-projects-are-using-this-flag "Direct link to \"Which projects are using this flag?\"")
###### Nov 2, 2021[](#nov-2-2021 "Direct link to Nov 2, 2021")
ConfigCat: "Say no more fam! Let me show you!"
[See the documentation for details](https://configcat.com/docs/advanced/code-references/overview.md)
***
#### Searching feature flags instead of Ctrl+F[](#searching-feature-flags-instead-of-ctrlf "Direct link to Searching feature flags instead of Ctrl+F")
###### Oct 5, 2021[](#oct-5-2021 "Direct link to Oct 5, 2021")
Added a search bar to the feature flags page.
We recommend using it instead of Ctr+F and Cmd+F since the page is lazy loaded. So it might not yield results from parts of the page that are not currently rendered.
***
#### Environment colors are finally here[](#environment-colors-are-finally-here "Direct link to Environment colors are finally here")
###### Sep 24, 2021[](#sep-24-2021 "Direct link to Sep 24, 2021")
Just updated the UX on the product overview page and added a few small features.
* You can choose from a number of colors for your environments.
* Also adding descriptions helps teammates to find their way around environments and configs.
[Set your colors and add descriptions on the product overview page on our Dashboard](https://app.configcat.com/product)
***
#### Send less invitations using SAML SSO, Auto-assign users and product join requests[](#send-less-invitations-using-saml-sso-auto-assign-users-and-product-join-requests "Direct link to Send less invitations using SAML SSO, Auto-assign users and product join requests")
###### Sep 23, 2021[](#sep-23-2021 "Direct link to Sep 23, 2021")
To make organization level user management more convenient we added a bunch of new features:
* Added an [organization overview on our Dashboard page](https://app.configcat.com/) to see products more clearly.
* Team members can send join requests to admins if they want to join a product.
* Whenever someone signs up to ConfigCat using a verified email domain, they could be automatically assigned to products.
* SAML Single Sign-On supporting all of the major identity providers.
* Improved layout for admins to [manage organization members](https://app.configcat.com/organization/members) on our Dashboard page.
*Only team members with Organization Admin role can access these features.*
[Set up user provisioning and SAML Single Sign-On on our Dashboard](https://app.configcat.com/organization/authentication)
***
#### New Organization Admin functionalities[](#new-organization-admin-functionalities "Direct link to New Organization Admin functionalities")
###### Aug 13, 2021[](#aug-13-2021 "Direct link to Aug 13, 2021")
* Organization Admins can remove a member from the whole organization.
* Organization Admins can modify a member's permissions globally.
*Only team members with Organization Admin role can access these features.*
[Open Organization Members & Roles page on our Dashboard](https://app.configcat.com/organization/members)
***
#### Disable Two-factor authentication[](#disable-two-factor-authentication "Direct link to Disable Two-factor authentication")
###### Aug 4, 2021[](#aug-4-2021 "Direct link to Aug 4, 2021")
Disable Two-factor authentication for your team members. This feature is useful if somebody lost the device used for Two-factor authentication.
*Only team members with Organization Admin role can disable Two-factor authentication.*
[Open Organization Members & Roles page on our Dashboard](https://app.configcat.com/organization/members)
***
#### Export / Import[](#export--import "Direct link to Export / Import")
###### Jul 28, 2021[](#jul-28-2021 "Direct link to Jul 28, 2021")
Export (download), and import (upload) Configs, Environments, and Feature Flags from, and to file.
[Open Export / Import page on our Dashboard](https://app.configcat.com/product/exportimport)
***
#### Dashboard v3 released[](#dashboard-v3-released "Direct link to Dashboard v3 released")
###### Jun 30, 2021[](#jun-30-2021 "Direct link to Jun 30, 2021")
Hope you like it.
Tell us your opinion over [Slack](https://configcat.com/slack) or [Email](mailto:team@configcat.com).
***
#### Help us grow[](#help-us-grow "Direct link to Help us grow")
###### Jun 10, 2021[](#jun-10-2021 "Direct link to Jun 10, 2021")
If you like ConfigCat, you can help us grow by leaving a review. Plus Capterra is giving **20€ as a reward** to the first 100 reviewers.
Any of the following works:
* [TrustRadius](https://www.trustradius.com/welcome/configcat)
* [Trust Pilot](https://www.trustpilot.com/evaluate/configcat.com)
* [G2 Crowd](https://www.g2.com/products/configcat/reviews/start)
* [Capterra](https://reviews.capterra.com/new/187099) (**20€ reward**)
* [Alternative.me](https://alternative.me/configcat)
* [AlternativeTo](https://alternativeto.net/software/configcat/reviews)
***
#### Visual Studio Code Extension[](#visual-studio-code-extension "Direct link to Visual Studio Code Extension")
###### May 06, 2021[](#may-06-2021 "Direct link to May 06, 2021")
Turn your features On / Off and manage your Feature Flags from Visual Studio Code.
* [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=ConfigCat.configcat-feature-flags)
***
#### Detailed Permission Group system[](#detailed-permission-group-system "Direct link to Detailed Permission Group system")
###### Mar 10, 2021[](#mar-10-2021 "Direct link to Mar 10, 2021")
Permission Groups can be customized in more advanced levels:
* Resource-based permissions (Configs, Environments, Tags, Webhooks)
* Create/Update and Delete permissions are separated
* Team member management permission
* Product preferences permission
* Product Audit Log/Statistics permission
* Integration management permission
* SDK Key View/Rotate permissions
* [Fine-tune Permission Groups on our Dashboard](https://app.configcat.com/product/permission-groups)
***
#### Zombie Flags (Stale Flags) Report via email[](#zombie-flags-stale-flags-report-via-email "Direct link to Zombie Flags (Stale Flags) Report via email")
###### Mar 4, 2021[](#mar-4-2021 "Direct link to Mar 4, 2021")
Feature flags have a tendency to multiply rapidly. In order to keep the tech-debt low, we recommend removing the flags no longer needed. You can now set up a regular email report with a list of these zombie or stale flags.
* [Set up the Zombie Flags Report on our Dashboard](https://app.configcat.com/zombie-flags-report)
***
#### Invoice download[](#invoice-download "Direct link to Invoice download")
###### Feb 8, 2021[](#feb-8-2021 "Direct link to Feb 8, 2021")
You can download all your current and previous invoices from the Billing & Invoices page.
* [Open Billing & Invoices on our Dashboard](https://app.configcat.com/organization/billing)
***
#### Accepting USD payments[](#accepting-usd-payments "Direct link to Accepting USD payments")
###### Nov 26, 2020[](#nov-26-2020 "Direct link to Nov 26, 2020")
We are accepting payments in USD from now on.
* [See plans on our Dashboard](https://app.configcat.com/organization/plans)
***
#### ConfigCat & Zoho Flow[](#configcat--zoho-flow "Direct link to ConfigCat & Zoho Flow")
###### Nov 21, 2020[](#nov-21-2020 "Direct link to Nov 21, 2020")
ConfigCat's Zoho Flow integration is now available.
* [Detailed Docs and Setup Guide](https://configcat.com/docs/integrations/zoho-flow.md)
***
#### Default Permission Group[](#default-permission-group "Direct link to Default Permission Group")
###### Nov 13, 2020[](#nov-13-2020 "Direct link to Nov 13, 2020")
Set a default Permission Group for Team member invites. The chosen group will be the default on the permission group list when inviting others. So you can be sure not to invite someone as an admin by accident.
***
#### Amplitude integration[](#amplitude-integration "Direct link to Amplitude integration")
###### Oct 28, 2020[](#oct-28-2020 "Direct link to Oct 28, 2020")
Annotate your setting changes on your Amplitude charts.
* [Docs and Setup Guide](https://configcat.com/docs/integrations/amplitude.md)
***
#### ConfigCat Feature Flags Provider for Terraform[](#configcat-feature-flags-provider-for-terraform "Direct link to ConfigCat Feature Flags Provider for Terraform")
###### Oct 16, 2020[](#oct-16-2020 "Direct link to Oct 16, 2020")
Configure and access ConfigCat resources via Terraform.
* [ConfigCat Feature Flags Provider for Terraform](https://registry.terraform.io/providers/configcat/configcat/latest/docs)
***
#### Data Governance - Action required[](#data-governance---action-required "Direct link to Data Governance - Action required")
###### Oct 10, 2020[](#oct-10-2020 "Direct link to Oct 10, 2020")
Addressing global data handling and processing trends, we have introduced the Data Governance feature in ConfigCat. We require all our customers to make a statement if they want to use our:
* **Global CDN**: providing geo-location based load balancing on server nodes all around the globe to ensure low response times.
* **EU CDN**: Staying compliant with GDPR by using ConfigCat EU CDN. This way your data will never leave the EU.
* [Read more on Data Governance and CDN](https://configcat.com/docs/advanced/data-governance.md)
***
#### Organization Management[](#organization-management "Direct link to Organization Management")
###### Sep 07, 2020[](#sep-07-2020 "Direct link to Sep 07, 2020")
Featuring:
* **Organization Admin** and **Billing Manager** roles.
* General **security** preferences for the entire organization.
* Customizable **SSO** methods.
* Organization level **audit logs** and usage **statistics**.
* [See Docs](https://configcat.com/docs/organization.md)
***
#### Public Management API v1 released[](#public-management-api-v1-released "Direct link to Public Management API v1 released")
###### Jul 08, 2020[](#jul-08-2020 "Direct link to Jul 08, 2020")
You can programmatically **CREATE**, **UPDATE**, **DELETE** Feature Flags, Configs, Products and Environments from now on!
* [See Docs and examples](https://configcat.com/docs/api/reference/configcat-public-management-api.md)
***
#### Tags & Filtering[](#tags--filtering "Direct link to Tags & Filtering")
###### May 29, 2020[](#may-29-2020 "Direct link to May 29, 2020")
Add colored tags to your feature flags.
***
#### Jira Cloud Plugin[](#jira-cloud-plugin "Direct link to Jira Cloud Plugin")
###### May 28, 2020[](#may-28-2020 "Direct link to May 28, 2020")
Turn your features On / Off right from a Jira Issue.
* [ConfigCat Jira Cloud Plugin](https://marketplace.atlassian.com/apps/1222421/configcat-feature-flags?hosting=cloud\&tab=overview)
***
#### Slack App[](#slack-app "Direct link to Slack App")
###### April 12, 2020[](#april-12-2020 "Direct link to April 12, 2020")
Get updated via a Slack Channel message when someone changes a feature flag.
* [ConfigCat Feature Flags in Slack App Directory](https://configcat.slack.com/apps/A011CN2QZJB-configcat-feature-flags)
***
#### API Key --> SDK Key[](#api-key----sdk-key "Direct link to API Key --> SDK Key")
###### April 7, 2020[](#april-7-2020 "Direct link to April 7, 2020")
Renamed API Key to SDK Key since it was more confusing as the Public Management API went to production. The API and the API Key are not related. This is a breaking change in some of the SDKs, released under new major versions.
***
#### New JavaScript SDK for SSR[](#new-javascript-sdk-for-ssr "Direct link to New JavaScript SDK for SSR")
###### April 3, 2020[](#april-3-2020 "Direct link to April 3, 2020")
New JavaScript SDK supporting Server Side Rendered (SSR) frameworks like [NuxtJS](https://nuxtjs.org).
* [See Documentation](https://configcat.com/docs/sdk-reference/js-ssr.md)
***
#### Trello Power-Up[](#trello-power-up "Direct link to Trello Power-Up")
###### March 30, 2020[](#march-30-2020 "Direct link to March 30, 2020")
Turn your features On / Off right from a Trello Card.
* [ConfigCat Power-Up](https://trello.com/power-ups/5e694b66d2511a3601ebd0fb)
***
#### Integrations[](#integrations "Direct link to Integrations")
###### March 21, 2020[](#march-21-2020 "Direct link to March 21, 2020")
Connect the apps you use everyday and be more productive. Check out the [Integrations tab](https://app.configcat.com/product/integrations) in our Dashboard.
***
#### View SDK Key permission[](#view-sdk-key-permission "Direct link to View SDK Key permission")
###### March 21, 2020[](#march-21-2020-1 "Direct link to March 21, 2020")
Visibility of information that is normally useful for developers only - like SDK Keys and code examples - can be set for [Permission Groups](https://app.configcat.com/product/permission-groups) on our Dashboard.
***
#### Audit log improvements[](#audit-log-improvements "Direct link to Audit log improvements")
###### March 20, 2020[](#march-20-2020 "Direct link to March 20, 2020")
User friendly Feature Flag or Setting value changes in the [Audit log on our Dashboard](https://app.configcat.com/auditlog) to improve readability.
***
#### Long text improvements[](#long-text-improvements "Direct link to Long text improvements")
###### March 20, 2020[](#march-20-2020-1 "Direct link to March 20, 2020")
Feature Flag or Setting text values and Targeting comparison values can be viewed and updated in a `textarea`.
***
#### Upper case key generation mode[](#upper-case-key-generation-mode "Direct link to Upper case key generation mode")
###### March 17, 2020[](#march-17-2020 "Direct link to March 17, 2020")
Besides "camelCase" and "lower\_case" we have added an "UPPER\_CASE" key generation mode to preferences.
* [Open Preferences on in our Dashboard](https://app.configcat.com/product/preferences)
***
#### Statistics[](#statistics "Direct link to Statistics")
###### March 15, 2020[](#march-15-2020 "Direct link to March 15, 2020")
See detailed statistics about the number of config.json downloads made towards ConfigCat CDN. Also a pie-chart of the SDK types and versions being used.
* [Open Stats on our Dashboard](https://app.configcat.com/product/statistics)
***
#### ConfigCat Zap[](#configcat-zap "Direct link to ConfigCat Zap")
###### March 12, 2020[](#march-12-2020 "Direct link to March 12, 2020")
Zapier integration is now accessible.
* [Detailed Docs and Setup Guide](https://configcat.com/docs/integrations/zapier.md)
***
#### Public Management API (Beta)[](#public-management-api-beta "Direct link to Public Management API (Beta)")
###### March 11, 2020[](#march-11-2020 "Direct link to March 11, 2020")
Released Public Management API to Beta. From now on you can execute Dashboard management operations programmatically.
* [API Documentation](https://configcat.com/docs/api/reference/configcat-public-management-api.md)
***
#### Sensitive text comparators[](#sensitive-text-comparators "Direct link to Sensitive text comparators")
###### March 3, 2020[](#march-3-2020 "Direct link to March 3, 2020")
Introduced sensitive text comparators to make sure sensitive info (like email address, user name) is kept hidden in Targeting Rules. Comes handy in front-end applications.
* [Detailed Docs about comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparator)
* [Related blog post](https://configcat.com/blog/2020/03/02/sensitive-comparators/)
***
#### Semantic version based user targeting[](#semantic-version-based-user-targeting "Direct link to Semantic version based user targeting")
###### March 3, 2020[](#march-3-2020-1 "Direct link to March 3, 2020")
Especially useful for Mobile developers.
* [Detailed Docs about comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparator)
* [Related blog post](https://configcat.com/blog/2020/01/27/semver)
***
#### Ruby SDK[](#ruby-sdk "Direct link to Ruby SDK")
###### Oct 29, 2019[](#oct-29-2019 "Direct link to Oct 29, 2019")
It is out!
* [Ruby SDK Docs](https://configcat.com/docs/sdk-reference/ruby.md)
* [GitHub repo](https://github.com/configcat/ruby-sdk)
* [Blog post](https://configcat.com/blog/2019/10/29/ruby-sdk/)
***
---
## FAQ
### FAQ - Frequently Asked Questions
Copy page
A collection of frequently asked questions.
#### General[](#general "Direct link to General")
##### Learning how ConfigCat can work with your product[](#learning-how-configcat-can-work-with-your-product "Direct link to Learning how ConfigCat can work with your product")
You can book a free demo session [here](https://calendly.com/configcat/demo), where we'll show you how to use ConfigCat and answer any questions you have.
#### Billing, Payments & Subscriptions[](#billing-payments--subscriptions "Direct link to Billing, Payments & Subscriptions")
##### What if I exceed the [config JSON download](https://configcat.com/docs/requests.md) limit of my plan?[](#what-if-i-exceed-the-config-json-download-limit-of-my-plan "Direct link to what-if-i-exceed-the-config-json-download-limit-of-my-plan")
Don't worry, we will keep serving your data and feature flags. Someone from our team will contact you to discuss your options. You can always check your Usage & Quota [here](https://app.configcat.com/organization/usage).
##### Where can I find and download my invoices?[](#where-can-i-find-and-download-my-invoices "Direct link to Where can I find and download my invoices?")
All the invoices we've issued are available for download from the [Billing & Invoices page](https://app.configcat.com/organization/billing). You need to have the [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Billing & Invoices page.
##### Is it possible to pay via wire transfer?[](#is-it-possible-to-pay-via-wire-transfer "Direct link to Is it possible to pay via wire transfer?")
Using a credit card via the ConfigCat Dashboard is the preferred way of payment, but a wire transfer is also an option for larger subscription plans. [Contact us](https://configcat.com/support/) directly for more details.
##### How do I upgrade / downgrade my billing plan?[](#how-do-i-upgrade--downgrade-my-billing-plan "Direct link to How do I upgrade / downgrade my billing plan?")
You can change your billing plan on the [Plans](https://app.configcat.com/organization/plans) page. You need to have the [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Plans page.
##### Can I get a discounted rate?[](#can-i-get-a-discounted-rate "Direct link to Can I get a discounted rate?")
Discounts are available through our partnership program. [Contact us](https://configcat.com/support/) directly for more information.
##### Can I change the email address associated with my account?[](#can-i-change-the-email-address-associated-with-my-account "Direct link to Can I change the email address associated with my account?")
Currently, there's no direct way to change the email address of an account. However, you can:
1. Invite the new email to join your ConfigCat organization; this will create a fresh ConfigCat account.
2. Grant all the necessary permissions to the new account.
3. Proceed with deleting your old account from [here](https://app.configcat.com/my-account).
If you don't have the required permissions, contact your organization admin or a team member who has "Team members and permission groups" permissions.
Please note: Switching emails means you'll lose preferences from your old account, such as permissions, API keys, and Zombie flag settings. Transfer essential settings first.
##### How do I change the billing email address where I receive my invoices?[](#how-do-i-change-the-billing-email-address-where-i-receive-my-invoices "Direct link to How do I change the billing email address where I receive my invoices?")
Go to the [Billing & Invoices page](https://app.configcat.com/organization/billing) and click the `Update billing details` link. You need to have the [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Billing & Invoices page.
##### How do I change my payment method or billing information?[](#how-do-i-change-my-payment-method-or-billing-information "Direct link to How do I change my payment method or billing information?")
Go to the [Billing & Invoices page.](https://app.configcat.com/organization/billing) and click the `Update billing details` link. You need to have a [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Billing & Invoices page.
##### The ChargeBee payment gets stuck | Throws an error[](#the-chargebee-payment-gets-stuck--throws-an-error "Direct link to The ChargeBee payment gets stuck | Throws an error")
If you're using Firefox, try switching to a Chromium-based browser that has extensions turned off. If this doesn't work, [contact us](https://configcat.com/support/) for help.
##### How do I cancel my account?[](#how-do-i-cancel-my-account "Direct link to How do I cancel my account?")
Go to the [Plans](https://app.configcat.com/organization/plans) page and click the `Switch Plan` button under the Free plan. You need to have a [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Plans page.
##### How do I change my currency?[](#how-do-i-change-my-currency "Direct link to How do I change my currency?")
Go to the [Plans](https://app.configcat.com/organization/plans) page and use the currency toggle to switch between USD and EUR. You need to have a [Billing Manager](https://configcat.com/docs/organization.md#billing-manager-role) role to access the Plans page.
#### Security[](#security "Direct link to Security")
##### Are you ISO certified?[](#are-you-iso-certified "Direct link to Are you ISO certified?")
Yes, ConfigCat complies with the ISO/IEC 27001:2022 standard for Information Security Management Systems (ISMS). Click [here](https://configcat.com/iso/) to learn more.
##### I'm setting up my firewall, which addresses should I whitelist?[](#im-setting-up-my-firewall-which-addresses-should-i-whitelist "Direct link to I'm setting up my firewall, which addresses should I whitelist?")
If possible, you can allow the whole "configcat.com" domain. Alternatively, you can manually whitelist the following addresses:
* Global CDN: `https://cdn-global.configcat.com`
* EU CDN: `https://cdn-eu.configcat.com`
* The Public Management API:
* The Dashboard URL:
##### I can't log in to ConfigCat using two-factor authentication (2FA).[](#i-cant-log-in-to-configcat-using-two-factor-authentication-2fa "Direct link to I can't log in to ConfigCat using two-factor authentication (2FA).")
*Solution 1:* There might be an authenticator app on your phone that you can use to log in to ConfigCat.
*Solution 2:* Use your recovery codes that you received when you first set your 2FA up.
*Solution 3:* Contact your `Organization Admin`, and ask them to disable 2FA for your account until you set it up again. `Organization Admins` can disable 2FA on the [Members & Roles](https://app.configcat.com/organization/members) page. After you re-enable the 2FA, new recovery codes will also be (re)generated. It might be a good idea to save them to avoid such issues in the future.
##### The Audit log doesn't show old operations[](#the-audit-log-doesnt-show-old-operations "Direct link to The Audit log doesn't show old operations")
The Free plan includes a 7-day retention period. The Pro and Smart plans offer a 35-day retention, while the Enterprise and Dedicated plans provide a 2-year retention.
##### Is there a way to allow a group access to only one config rather than all of them?[](#is-there-a-way-to-allow-a-group-access-to-only-one-config-rather-than-all-of-them "Direct link to Is there a way to allow a group access to only one config rather than all of them?")
You can't set config-level access in one product. Instead, split your configs into multiple products with the appropriate permission settings.
##### I cannot access my account using Google sign-in.[](#i-cannot-access-my-account-using-google-sign-in "Direct link to I cannot access my account using Google sign-in.")
Browser extensions may interfere. Please disable all browser extensions and try again.
#### Privacy[](#privacy "Direct link to Privacy")
##### How can I be sure that my data is safe?[](#how-can-i-be-sure-that-my-data-is-safe "Direct link to How can I be sure that my data is safe?")
ConfigCat SDKs evaluate feature flags locally, in your application. They send no user data to the ConfigCat servers.
See our architecture explained [here](https://configcat.com/architecture/).
##### Can we sign a data processing agreement with you?[](#can-we-sign-a-data-processing-agreement-with-you "Direct link to Can we sign a data processing agreement with you?")
Yes. You can review our DPA through our [Trust Center](https://configcat.com/trust-center/) page, or [contact us](https://configcat.com/support/?prefilled=dpa-sign-request) and we'll send it to you for signing.
##### Does ConfigCat collect browser data when serving feature flag data download requests?[](#does-configcat-collect-browser-data-when-serving-feature-flag-data-download-requests "Direct link to Does ConfigCat collect browser data when serving feature flag data download requests?")
No. ConfigCat doesn't collect, store or process any user or browser fingerprinting data.
The data flow is one directional - the SDKs are only downloading the config JSON files and the feature flag evaluation happens in the SDKs.
ConfigCat doesn't collect any information about the customer's users.
##### Is data hosted only within the EU?[](#is-data-hosted-only-within-the-eu "Direct link to Is data hosted only within the EU?")
Our main infrastructure and database is in the EU, but CDN servers are located both in the EU and globally. You can set where you want us to keep your data, so its always within reach for your needs.
You can read more [here](https://configcat.com/docs/advanced/data-governance.md).
##### Is it possible to export the feature flags?[](#is-it-possible-to-export-the-feature-flags "Direct link to Is it possible to export the feature flags?")
Yes! You can export and download your current product as a standard JSON file anytime you want. The export will include:
* All feature flags and settings together with their values, Targeting Rules, Percentage Options, segments, tags
* All configs
* All environments
* All tags
* All segments
##### How long does ConfigCat keep my data?[](#how-long-does-configcat-keep-my-data "Direct link to How long does ConfigCat keep my data?")
We keep organization data as long as we see activity in that organization. After several months of inactivity, we send you a series of email notifications about or plans to delete your organization and all associated data. We consider an organization inactive if it meets all of the following criteria:
* no audit log events are generated in the organization,
* no valid calls are made to the organization via the Public Management API,
* config JSONs aren't downloaded from the ConfigCat CDN,
* the organization does not have an active paid subscription.
#### A/B Testing & Targeting[](#ab-testing--targeting "Direct link to A/B Testing & Targeting")
##### Can I use AND operators in my Targeting Rules?[](#can-i-use-and-operators-in-my-targeting-rules "Direct link to Can I use AND operators in my Targeting Rules?")
Yes, you can use AND operators in your Targeting Rules. (Only available in [Config V2](https://configcat.com/docs/advanced/config-v2.md) and later)
##### Are Percentage Options sticky?[](#are-percentage-options-sticky "Direct link to Are Percentage Options sticky?")
Yes. The percentage-based targeting is sticky by design and consistent across all SDKs.
Also, consider the following:
* All SDKs evaluate the rules in the exact same way. (10% is the same 10% in all SDKs)
* The percentage rules are sticky by feature flag. (10% is a different 10% for each feature flag)
More on [stickiness](https://configcat.com/docs/targeting/percentage-options.md#stickiness) and [consistency](https://configcat.com/docs/targeting/percentage-options.md#consistency)
##### How to use Targeting Rules based on sensitive data?[](#how-to-use-targeting-rules-based-on-sensitive-data "Direct link to How to use Targeting Rules based on sensitive data?")
If you want to use Targeting Rules based on email address, phone number, or other sensitive data, you can use the [Confidential text comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators).
#### Technical Debt[](#technical-debt "Direct link to Technical Debt")
##### What are Zombie (Stale) Flags?[](#what-are-zombie-stale-flags "Direct link to What are Zombie (Stale) Flags?")

Zombie (Stale) flags are feature flags that are not changed in the last (configurable) number of days. Most of the time if a feature flag isn't changed for a long time it means it is time to be removed from your source code and from the [ConfigCat Dashboard](https://app.configcat.com/) as well to avoid technical debt.
##### What is the Zombie (Stale) Flags Report?[](#what-is-the-zombie-stale-flags-report "Direct link to What is the Zombie (Stale) Flags Report?")
The [Zombie (Stale) Flags Report](https://app.configcat.com/my-account/zombie-flags-report) is a list of all feature flags that are not changed in the last (configurable) number of days. You can use this report to identify and remove stale feature flags from your source code. This report is weekly emailed to you. You can set your [email preferences here](https://app.configcat.com/my-account/zombie-flags-report).
##### I am not getting the Zombie Feature Flag email report. What am I doing wrong?[](#i-am-not-getting-the-zombie-feature-flag-email-report-what-am-i-doing-wrong "Direct link to I am not getting the Zombie Feature Flag email report. What am I doing wrong?")
You can change the frequency, criteria and scope of the Zombie Feature Flag report on the Dashboard.
**Note:** Please be aware that feature flags are only treated as zombie flags if they haven't been modified (with save & publish) in the past given timeframe. It currently doesn't have any connection with your real usage in your code.
##### How to avoid technical debt caused by feature flags?[](#how-to-avoid-technical-debt-caused-by-feature-flags "Direct link to How to avoid technical debt caused by feature flags?")
The [ConfigCat CLI](https://configcat.com/docs/advanced/code-references/overview.md) can scan your code, upload code references to the [ConfigCat Dashboard](https://app.configcat.com/) and notify you about stale feature flags.

##### Is there a way to compare flag statuses between two or more environments?[](#is-there-a-way-to-compare-flag-statuses-between-two-or-more-environments "Direct link to Is there a way to compare flag statuses between two or more environments?")
Yes, you can see the state of all your Feature Flags across all your environments in our simplified [overview](https://app.configcat.com/overview).
#### Joining an Organization[](#joining-an-organization "Direct link to Joining an Organization")
##### Is there an expiration date for sent invitations?[](#is-there-an-expiration-date-for-sent-invitations "Direct link to Is there an expiration date for sent invitations?")
Invitations are valid for 14 days by default, but you can re-send them anytime to extend their expiration.
##### I can't see the organization that I just joined[](#i-cant-see-the-organization-that-i-just-joined "Direct link to I can't see the organization that I just joined")
If you created a new account before joining an organization via an invite (like the one sent by your company via email), then it is likely that a duplicate organization is created for you by ConfigCat.
Once you find the proper organization where you are supposed to be, we recommend deleting the duplicate from [here](https://app.configcat.com/organization/preferences), but please make sure that you don't accidentally delete the one that you want to keep.
#### Technical Ones[](#technical-ones "Direct link to Technical Ones")
##### Is it possible to rename a product or config?[](#is-it-possible-to-rename-a-product-or-config "Direct link to Is it possible to rename a product or config?")
Yes, you can rename almost everything within ConfigCat. Organizations, products, configs, environments, tags and feature flags can all be renamed. What you can't rename is feature flag keys, as that could cause a tsunami of reference error messages in your applications.
##### Can I change my Feature Flag based on a date?[](#can-i-change-my-feature-flag-based-on-a-date "Direct link to Can I change my Feature Flag based on a date?")
You can pass the current date as a [custom User Object attribute](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparison-attribute) to the ConfigCat SDK attribute when evaluating the feature flag, and you can use that attribute with our [Date and Time comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#date-and-time-comparators) in your targeting rules to target specific dates.
##### Does ConfigCat guarantee percentage distribution?[](#does-configcat-guarantee-percentage-distribution "Direct link to Does ConfigCat guarantee percentage distribution?")
ConfigCat guarantees percentage distribution across all SDKs, and it guarantees that each user will receive the same experience every time.
##### Is it possible to set up A/B/C test (33%/33%/33%) distribution with ConfigCat?[](#is-it-possible-to-set-up-abc-test-333333-distribution-with-configcat "Direct link to Is it possible to set up A/B/C test (33%/33%/33%) distribution with ConfigCat?")
Yes, it is possible. All you have to do is to create a text setting and apply the percentage rules. With a normal feature flag you have only two options - true or false, but with a text setting you can apply as many A/B/n options as you want with the percentages.
##### Is there a way to create feature flags via the API?[](#is-there-a-way-to-create-feature-flags-via-the-api "Direct link to Is there a way to create feature flags via the API?")
Yes there is. We have a public management API at .
##### How to resolve Domain verification issues?[](#how-to-resolve-domain-verification-issues "Direct link to How to resolve Domain verification issues?")
**Txt record-based verification**
**Solution 1:** Check the 'Host' field in your DNS settings. One common cause of verification failure is an incorrectly set 'Host' field. Make sure that it is set to '@' or left empty. To check this setting, you will need to log into your domain provider's management console.
**Solution 2:** After you've added the TXT record to your DNS settings, it may take some time for the changes to propagate through the DNS system. If you have recently added or updated the TXT record, it's possible that the verification hasn't been completed due to DNS caching. Sometimes you even need to wait a few hours before trying to verify the domain again.
**File-Based verification**
If you're having trouble verifying your domain with the file-based verification method, make sure you've uploaded the file to the proper directory, and you can download it from under your domain.
---
## Glossary
### Glossary of Terms
Copy page
An alphabetical list of terms used around feature management and software development in general in the context of ConfigCat.
#### A[](#a "Direct link to A")
###### [A/B Testing](https://configcat.com/blog/2022/05/02/what-is-ab-testing/)[](#ab-testing "Direct link to ab-testing")
A/B testing is a method of comparing two versions of a product or feature to determine which one performs better. A/B testing is a form of controlled experimentation.
###### [Alpha Testing](https://configcat.com/docs/glossary/alpha-testing.md)[](#alpha-testing "Direct link to alpha-testing")
Alpha testing examines a product's functionality and compliance with the business requirements through the initial end-to-end testing.
#### B[](#b "Direct link to B")
###### [Beta Testing](https://configcat.com/docs/glossary/beta-testing.md)[](#beta-testing "Direct link to beta-testing")
Testing in the beta phase allows users to discover any issues or bugs before a general release by using a product in a real-world environment.
###### [Blue/Green Deployment](https://configcat.com/docs/glossary/blue-green-deployment.md)[](#bluegreen-deployment "Direct link to bluegreen-deployment")
Blue/Green deployments offer near-zero downtime and rollback capabilities. The concept of a blue/green deployment involves switching traffic between two identical environments running different versions of your application.
#### C[](#c "Direct link to C")
###### [Canary Release](https://configcat.com/canary-testing)[](#canary-release "Direct link to canary-release")
A Canary Release is a type of progressive delivery where a small percentage of users are exposed to a new feature. If the feature works as expected, the percentage of users exposed to the feature is increased. If the feature does not work as expected, the feature is rolled back.
###### [Canary Testing](https://configcat.com/canary-testing/)[](#canary-testing "Direct link to canary-testing")
Canary testing is a software deployment technique where updates or new features are rolled out to a small, carefully selected subset of users before being released to the entire user base, to test and ensure their effectiveness and safety.
###### [CI/CD Pipeline](https://configcat.com/docs/glossary/ci-cd-pipeline.md)[](#cicd-pipeline "Direct link to cicd-pipeline")
A CI/CD (Continuous Integration and Continuous Deployment) pipeline is a set of steps that must be followed to deliver a new software version to customers.
###### [Continuous Delivery](https://configcat.com/blog/2022/06/13/decoupling-feature-releases-from-deployment/)[](#continuous-delivery "Direct link to continuous-delivery")
A continuous delivery process enables changes - including new features, configuration changes, bug fixes and experiments - to be released into production in a safe and timely manner while maintaining sustainability.
###### [Continuous Deployment](https://configcat.com/blog/2022/06/13/decoupling-feature-releases-from-deployment/)[](#continuous-deployment "Direct link to continuous-deployment")
Continuous Deployment is a process where any code changes brought to an application are released automatically into the production environment.
###### [Continuous Integration](https://configcat.com/docs/glossary/continuous-integration.md)[](#continuous-integration "Direct link to continuous-integration")
Continuous Integration refers to the regular merging of code changes into a central repository, followed by automated builds and tests.
#### D[](#d "Direct link to D")
###### [Dark Launch](https://configcat.com/blog/2022/06/13/decoupling-feature-releases-from-deployment/#feature-release-with-dark-launch)[](#dark-launch "Direct link to dark-launch")
A dark launch involves releasing a feature to a subset of users before a full release to test reactions.
###### [Developer Advocate](https://configcat.com/blog/2023/07/11/role-of-developer-advocates/)[](#developer-advocate "Direct link to developer-advocate")
A Developer Advocate is a person whose job is to help developers be successful with a platform or a technology and to speak (or write) on their behalf.
###### [DevOps Engineer](https://configcat.com/docs/glossary/devops-engineer.md)[](#devops-engineer "Direct link to devops-engineer")
The DevOps Engineer is responsible for the development and maintenance of the infrastructure and the deployment of the software. The DevOps Engineer is also responsible for the monitoring and maintenance of the software and the infrastructure.
#### E[](#e "Direct link to E")
#### F[](#f "Direct link to F")
###### [Fake Door Testing](https://configcat.com/fake-door-testing/)[](#fake-door-testing "Direct link to fake-door-testing")
Fake Door Testing is a technique used to assess the market demand for a product prior to investing in its development.
###### [Feature Branch](https://configcat.com/feature-branch/)[](#feature-branch "Direct link to feature-branch")
A feature branch is a copy of the main codebase where an individual or team of software developers can work on a new feature until it is complete.
###### [Feature Flag](https://configcat.com/featureflags/)[](#feature-flag "Direct link to feature-flag")
A feature flag is a toggle used to activate or deactivate specific features you may have in your application without redeploying code.
###### [Feature Testing](https://configcat.com/docs/glossary/feature-testing.md)[](#feature-testing "Direct link to feature-testing")
An experiment to determine which version of a feature offers the best user experience is called a Feature Test.
###### [Feature Flag Framework](https://configcat.com/feature-flag-framework-explained/)[](#feature-flag-framework "Direct link to feature-flag-framework")
A feature flag framework is a system that allows developers to enable or disable specific functionalities of an application, enabling testing, gradual rollouts, and easy adjustments without redeploying the whole software.
###### [Feature Flagging Tools](https://configcat.com/feature-flagging-tools/)[](#feature-flagging-tools "Direct link to feature-flagging-tools")
Feature flagging tools are software utilities that enable developers to control the visibility and operational state of individual features in a software product, allowing for selective exposure and A/B testing without requiring system-wide updates or redeployments.
###### [Feature Flags as a Service](https://configcat.com/feature-flag-as-a-service/)[](#feature-flags-as-a-service "Direct link to feature-flags-as-a-service")
Providing feature flags as a service involves delivering (under a subscription model) a cloud solution for managing software features, enhancing development efficiency, risk control, and user experience.
###### [Feature Toggles](https://configcat.com/feature-toggles/)[](#feature-toggles "Direct link to feature-toggles")
Feature toggles, also known as feature flags, are a software development technique that allows the enabling or disabling of specific functionalities within an application, facilitating testing, incremental rollouts, and feature control without redeploying the software.
###### [Feature Toggle Management](https://configcat.com/feature-toggle-management/)[](#feature-toggle-management "Direct link to feature-toggle-management")
Feature toggle management refers to the process of controlling and coordinating the use of feature flags or toggles in software development, enabling developers to switch on or off certain functionalities for testing, deployment, or user experience customization.
#### G[](#g "Direct link to G")
#### H[](#h "Direct link to H")
#### I[](#i "Direct link to I")
#### J[](#j "Direct link to J")
#### K[](#k "Direct link to K")
###### [Kill Switch](https://configcat.com/blog/2022/03/24/how-kantan-successfully-uses-configcat-in-its-ci-pipeline/#retiring-feature-flags-or-keeping-them-as-emergency-kill-switches)[](#kill-switch "Direct link to kill-switch")
A kill switch is a mechanism that can be used to quickly disable a feature or an entire application in case of an emergency.
#### L[](#l "Direct link to L")
#### M[](#m "Direct link to M")
###### [Multi-Armed Bandit](https://configcat.com/docs/glossary/multi-armed-bandit.md)[](#multi-armed-bandit "Direct link to multi-armed-bandit")
The Multi-Armed Bandit (MAB) is a machine learning framework that involves an agent making selections, referred to as "arms," with the goal of maximizing long-term cumulative rewards.
#### N[](#n "Direct link to N")
#### O[](#o "Direct link to O")
#### P[](#p "Direct link to P")
###### [Product Lifecycle Manager](https://configcat.com/docs/glossary/product-lifecycle-manager.md)[](#product-lifecycle-manager "Direct link to product-lifecycle-manager")
The role of a product lifecycle manager is to supervise the project team and ensure timely completion of each stage in the lifecycle of a project.
###### [Platform Engineering](https://configcat.com/platform-engineering/)[](#platform-engineering "Direct link to platform-engineering")
Platform engineering is the design and maintenance of the foundational infrastructure and tools that support software development teams in building, deploying, and operating applications at scale. It combines elements of systems and software engineering with automation to provide standardized environments and CI/CD pipelines, enabling developers to focus on code while minimizing infrastructure complexity.
###### [Progressive Delivery](https://configcat.com/blog/2022/01/14/progressive-delivery/)[](#progressive-delivery "Direct link to progressive-delivery")
A progressive delivery approach to DevOps combines the principles of Continuous Integration and Continuous Delivery (CI/CD) with modern software development practices, facilitating faster code deployment, reducing risk, and improving user experiences.
#### Q[](#q "Direct link to Q")
#### R[](#r "Direct link to R")
###### [Rails Feature Flags](https://configcat.com/rails-feature-flag/)[](#rails-feature-flags "Direct link to rails-feature-flags")
Rails feature flags are conditional coding elements used in Ruby on Rails applications that enable or disable specific features dynamically, facilitating controlled release, A/B testing, and gradual rollout of software functionalities.
###### [React Feature Flags](https://configcat.com/react-feature-flag/)[](#react-feature-flags "Direct link to react-feature-flags")
React feature flags are conditional codes used in React.js applications to enable or disable certain features dynamically, allowing for controlled release, testing, and customization of software functionalities.
###### [Release Manager](https://configcat.com/docs/glossary/release-manager.md)[](#release-manager "Direct link to release-manager")
A release manager is an IT professional responsible for defining and executing the software release process within a company, ensuring smooth deployment and high-quality releases.
###### [Remote Configuration](https://configcat.com/docs/glossary/remote-configuration.md)[](#remote-configuration "Direct link to remote-configuration")
Remote configuration is a software development technique that allows you to modify certain features of an app remotely without having to deploy a new version of the app.
###### [Ring Deployment](https://configcat.com/ring-deployment/)[](#ring-deployment "Direct link to ring-deployment")
Ring deployment is a form of gradual rollout where new features are released gradually to different groups of users to mitigate risk.
#### S[](#s "Direct link to S")
###### [Site Reliability Engineer](https://configcat.com/site-reliability-engineers/)[](#site-reliability-engineer "Direct link to site-reliability-engineer")
A site reliability engineer (SRE) is a professional in the field of information technology who uses automation tools to monitor the reliability of software in a live production environment.
###### [Smoke Testing](https://configcat.com/docs/glossary/smoke-testing.md)[](#smoke-testing "Direct link to smoke-testing")
Smoke testing is a type of testing done early in the software development process to confirm that the most critical features of an application are functioning correctly.
###### [Soak Testing](https://configcat.com/soak-testing/)[](#soak-testing "Direct link to soak-testing")
Soak testing is a type of non-functional testing that assesses a software application's performance under a high volume of load over an extended period of time.
###### [Software Development Life Cycle](https://configcat.com/software-development-lifecycle/)[](#software-development-life-cycle "Direct link to software-development-life-cycle")
The Software Development Life Cycle (SDLC) is a systematic approach aimed at producing high-quality, low-cost software efficiently and within a shorter timeframe.
###### [Software as a Service](https://configcat.com/feature-flag-saas/)[](#software-as-a-service "Direct link to software-as-a-service")
Software as a Service (SaaS) is a cloud-based delivery model where applications are hosted and maintained by a service provider and accessed by users over the internet, typically on a subscription basis.
###### [Staging Environment](https://configcat.com/docs/glossary/what-is-a-staging-environment.md)[](#staging-environment "Direct link to staging-environment")
A staging environment is a dry run for your code under the closest possible parameters to its real-world application. It is a near-perfect replica of the servers, infrastructure, architecture, and application of the actual production environment your code will run in. The key difference is that it is completely walled off from the front-facing actual environment.
#### T[](#t "Direct link to T")
###### [Testing in Production](https://configcat.com/testing-in-production/)[](#testing-in-production "Direct link to testing-in-production")
Testing in production is the practice of evaluating software in its live environment, with real users and real-world conditions. Unlike traditional testing in controlled settings, this approach exposes the software to actual usage scenarios, uncovering issues that may be missed otherwise. However, it requires vigilant monitoring and quick problem resolution to minimize user impact.
###### [Type I and Type II Errors](https://configcat.com/docs/glossary/type-i-and-type-ii-errors.md)[](#type-i-and-type-ii-errors "Direct link to type-i-and-type-ii-errors")
A Type I error occurs when the null hypothesis is incorrectly rejected, even though it is actually true. A Type II error occurs when the null hypothesis is wrongly not rejected while it is actually false.
###### [Trunk-Based Development](https://configcat.com/trunk-based-development/)[](#trunk-based-development "Direct link to trunk-based-development")
Trunk-based development is a version control technique where developers regularly merge small updates into a central "trunk" or main branch.
#### U[](#u "Direct link to U")
###### [User Acceptance Testing](https://configcat.com/user-acceptance-testing/)[](#user-acceptance-testing "Direct link to user-acceptance-testing")
User Acceptance Testing (UAT) is a stage in software development where the software is tested in a simulated real-world environment by its intended users or business representatives.
#### V[](#v "Direct link to V")
###### [Version Control](https://configcat.com/docs/glossary/version-control.md)[](#version-control "Direct link to version-control")
Version control, also referred to as source control or revision control, is a crucial software development practice that tracks and manages changes to code and other files, and is closely linked to source code management.
#### W[](#w "Direct link to W")
#### X[](#x "Direct link to X")
#### Y[](#y "Direct link to Y")
#### Z[](#z "Direct link to Z")
---
### Alpha Testing - The Unsung Hero of Product Development
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the vast world of software development, testing plays a pivotal role in ensuring that products not only function as intended but also provide a seamless user experience. Among the various testing methodologies, alpha testing often stands out as a critical early-stage evaluation process. Let's delve into the nuances of alpha testing and understand its significance in the product development lifecycle.
#### What is Alpha Testing?[](#what-is-alpha-testing "Direct link to What is Alpha Testing?")
Alpha testing is an in-house testing methodology conducted to identify bugs and issues before a product is released to a select group of external users. Typically performed by developers or QA teams, this type of testing is done in a controlled environment and aims to mimic real-world scenarios to ensure the software's functionality and reliability.
#### The Objectives of Alpha Testing[](#the-objectives-of-alpha-testing "Direct link to The Objectives of Alpha Testing")
* **Bug Identification**: Detecting and addressing glitches, errors, and other issues.
* **Functionality Verification**: Ensuring all features work as intended.
* **Usability Assessment**: Evaluating the product's user-friendliness and overall experience.
* **Performance Evaluation**: Checking the software's response times, load times, and overall efficiency.
#### The Alpha Testing Process[](#the-alpha-testing-process "Direct link to The Alpha Testing Process")
* **Planning**: Setting the scope, objectives, and timelines for the test.
* **Environment Setup**: Creating a controlled environment that simulates real-world usage.
* **Test Execution**: Running a series of tests, both manual and automated, to evaluate different aspects of the software.
* **Feedback Collection**: Gathering insights and observations from the testing team.
* **Issue Resolution**: Addressing and rectifying identified problems before moving to the next testing phase.
#### Why Alpha Testing is Crucial[](#why-alpha-testing-is-crucial "Direct link to Why Alpha Testing is Crucial")
* **Early Detection**: Catching issues early on can save time, effort, and resources in the later stages of development.
* **Internal Feedback**: Gaining valuable insights from the team members who are familiar with the product's objectives and design.
* **Risk Mitigation**: Reducing the chances of major issues appearing in subsequent testing phases or post-launch.
* **Enhanced User Experience**: Ensuring that the end-users get a product that is polished, functional, and user-friendly.
#### Challenges in Alpha Testing and Solutions[](#challenges-in-alpha-testing-and-solutions "Direct link to Challenges in Alpha Testing and Solutions")
* **Limited Perspective**: Being an internal process, alpha testing might miss issues that external users might encounter. Solution: Diverse testing teams and scenario simulations.
* **Environment Limitations**: The controlled environment might not perfectly mimic all real-world scenarios. Solution: Use of virtual machines and diverse testing tools.
* **Feedback Management**: Handling and prioritizing the feedback can be challenging. Solution: Use of feedback management tools and regular team sync-ups.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Alpha testing, while often overshadowed by its successor, beta testing, holds immense value in the software development process. By ensuring that a product is rigorously tested in its early stages, developers can pave the way for smoother subsequent testing phases and, ultimately, a successful product launch. As the adage goes, "Well begun is half done," and alpha testing ensures that software development begins on the right foot.
---
### Beta Testing - Navigating the Road to Market Readiness
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
Beta testing stands as a critical milestone before a software product meets its audience. This phase is the trial test, bridging the gap between internal development and user experience. Let's explore the role of beta testing in software development and its significance in refining software products.
#### What is Beta Testing in Software Development?[](#what-is-beta-testing-in-software-development "Direct link to What is Beta Testing in Software Development?")
Beta testing in software development involves releasing a near-complete version of the software to a selected group of external users. This phase follows alpha testing and is crucial for gathering feedback under real usage conditions to fine-tune the software before its official release.
#### The Objectives of Beta Testing in Software Development[](#the-objectives-of-beta-testing-in-software-development "Direct link to The Objectives of Beta Testing in Software Development")
* **Gathering User Feedback**: Collecting insights about user experiences and preferences.
* **Assessing Market Response**: Evaluating how the software is perceived and received in the market.
* **Identifying Real-World Bugs**: Detecting issues that might have been missed during internal testing.
* **Refinement for Market Launch**: Adjusting and improving the software based on user feedback.
#### The Beta Testing Process in Software Development[](#the-beta-testing-process-in-software-development "Direct link to The Beta Testing Process in Software Development")
* **Selection of Beta Testers**: Recruiting a diverse and representative sample of the target user base.
* **Distribution of Beta Version**: Providing the beta software to the chosen testers.
* **Monitoring and Feedback Collection**: Observing user interactions and gathering structured feedback.
* **Analysis and Iteration**: Analyzing user feedback to identify areas for improvement and implementing changes.
* **Release Readiness Assessment**: Evaluating if the software is ready for public launch based on tester feedback.
#### Why Beta Testing is Crucial in Software Development[](#why-beta-testing-is-crucial-in-software-development "Direct link to Why Beta Testing is Crucial in Software Development")
* **Insights from Real Users**: Obtaining feedback from actual users in varied real-world scenarios.
* **Market Acceptance Evaluation**: Gauging the market's reaction and the software's readiness for launch.
* **Enhancement of Software Quality**: Identifying and fixing bugs, and polishing features to improve overall quality.
* **Building Early User Base**: Establishing an initial user community and fostering early adopter loyalty.
#### Challenges in Beta Testing for Software and Solutions[](#challenges-in-beta-testing-for-software-and-solutions "Direct link to Challenges in Beta Testing for Software and Solutions")
* **Diverse User Scenarios**: Testers may have different usage patterns and environments. Solution: Carefully select a diverse group of beta testers.
* **Handling Feedback Effectively**: Managing a large volume of feedback can be challenging. Solution: Implement structured feedback collection tools and clear guidelines.
* **Maintaining Tester Engagement**: Keeping beta testers motivated and engaged throughout the process. Solution: Provide incentives for participation and maintain open, responsive communication channels.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Beta testing in software development is more than just a phase; it's a strategic approach to ensuring that the software not only functions but also resonates with its intended audience. It’s a vital step in the journey towards launching a software product that is not just functional, but also aligned with user expectations and market demands. Through beta testing, software developers can pave the way for a successful product launch, grounded in quality, user satisfaction, and market readiness.
---
### Blue/Green Deployment - Streamlining Software Releases
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the dynamic realm of software development, deploying updates without disrupting user experience is paramount. Blue/Green Deployment emerges as a strategic method that enables this seamless transition. Let's delve into its mechanics and recognize its significance in software deployment.
#### What is Blue/Green Deployment?[](#what-is-bluegreen-deployment "Direct link to What is Blue/Green Deployment?")
Blue/Green Deployment is a strategy used to reduce downtime and risk by running two identical production environments. Simply put, the 'Blue' environment is the active one, while the 'Green' is a clone, ready to be switched over at any moment. This approach allows for testing in the production environment itself without affecting users.
#### Objectives of Blue/Green Deployment[](#objectives-of-bluegreen-deployment "Direct link to Objectives of Blue/Green Deployment")
* **Minimal Downtime**: Achieve nearly zero downtime during deployments.
* **Risk Reduction**: Mitigate risks associated with the release of new features or updates.
* **Rapid Rollback**: Provide the ability to quickly revert to the previous version if issues arise post-deployment.
* **Continuous Delivery**: Facilitate a smoother continuous delivery pipeline.
#### The Blue/Green Deployment Process[](#the-bluegreen-deployment-process "Direct link to The Blue/Green Deployment Process")
* **Preparation**: Setting up two identical environments — Blue (current) and Green (new).
* **Testing**: Validating the Green environment to ensure it's ready for live traffic.
* **Routing Traffic**: Shifting user traffic from Blue to Green seamlessly.
* **Monitoring**: Keeping a close watch on the Green environment for any issues.
* **Finalization or Rollback**: If successful, decommission the Blue environment, or if problems are detected, revert traffic back to Blue.
#### Why Blue/Green Deployment is Essential[](#why-bluegreen-deployment-is-essential "Direct link to Why Blue/Green Deployment is Essential")
* **Enhanced Reliability**: Increases the reliability of the deployment process.
* **User Experience**: Ensures uninterrupted service to users during updates.
* **Simplified Troubleshooting**: Allows easy identification and resolution of issues.
* **Flexibility**: Offers flexibility in managing and scheduling deployments.
#### Challenges in Blue/Green Deployment and Solutions[](#challenges-in-bluegreen-deployment-and-solutions "Direct link to Challenges in Blue/Green Deployment and Solutions")
* **Resource Intensiveness**: Requires duplicating the production environment. Solution: Efficient resource management and cloud-based solutions.
* **Data Synchronization**: Keeping data in sync between Blue and Green environments. Solution: Robust data management strategies and tools.
* **Complex Configuration**: Managing complex configurations during the switch. Solution: Automation tools and thorough planning.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Blue/Green Deployment serves as a cornerstone for modern software delivery, ensuring that updates and new features are rolled out smoothly, without disturbing the end-user experience. By integrating this strategy into deployment practices, organizations can enhance the reliability and efficiency of their software delivery process, ultimately leading to greater user satisfaction and business success.
---
### CI/CD Pipeline - Streamlining Software Delivery
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the ever-evolving realm of software development, efficiency and speed are paramount. The CI/CD pipeline emerges as a cornerstone in achieving these goals, merging coding, testing, and deployment into a streamlined and automated process. Let’s unpack the components of CI/CD pipelines and their impact on software delivery.
#### What is a CI/CD Pipeline?[](#what-is-a-cicd-pipeline "Direct link to What is a CI/CD Pipeline?")
CI/CD stands for Continuous Integration and Continuous Deployment/Delivery. This method introduces automation into the development process to enable frequent application delivery to customers. The primary concepts central to CI/CD include continuous integration, continuous delivery, and continuous deployment.
#### The Objectives of a CI/CD Pipeline[](#the-objectives-of-a-cicd-pipeline "Direct link to The Objectives of a CI/CD Pipeline")
* **Rapid Deployment**: Facilitating frequent and reliable software updates.
* **Quality Assurance**: Ensuring consistent quality and performance through automated testing.
* **Risk Reduction**: Minimizing errors and issues in production through early detection.
* **Efficient Development**: Streamlining the development process for faster turnaround times.
#### The CI/CD Pipeline Process[](#the-cicd-pipeline-process "Direct link to The CI/CD Pipeline Process")
* **Code Integration**: Developers merge their changes into a shared repository, triggering automated builds and tests.
* **Automated Testing**: The integrated code is automatically tested for bugs, performance issues, and other potential problems.
* **Deployment**: Upon successful testing, the code is deployed to a staging or production environment.
* **Monitoring and Feedback**: Continuous monitoring of the application's performance and gathering feedback for future improvements.
#### Why CI/CD Pipelines are Essential[](#why-cicd-pipelines-are-essential "Direct link to Why CI/CD Pipelines are Essential")
* **Speedy Deliveries**: Accelerates the process of getting software improvements to end-users.
* **Enhanced Collaboration**: Fosters a collaborative environment where code integration and problem-solving happen in real-time.
* **Adaptability**: Allows for quick adaptation to market changes and user feedback.
* **Cost-Effectiveness**: Reduces costs associated with manual processes and delayed releases.
#### Challenges in CI/CD Pipeline and Solutions[](#challenges-in-cicd-pipeline-and-solutions "Direct link to Challenges in CI/CD Pipeline and Solutions")
* **Complex Integration**: Integrating various tools and platforms can be challenging. Solution: Utilize versatile CI/CD tools that offer broad integration capabilities.
* **Security Concerns**: Continuous deployment could introduce security vulnerabilities. Solution: Implement robust security checks within the pipeline.
* **Managing Dependencies**: Handling dependencies in a constantly changing environment. Solution: Effective dependency management strategies and tools.
#### Conclusion[](#conclusion "Direct link to Conclusion")
The CI/CD pipeline is more than just a development strategy; it’s a catalyst for agility, quality, and innovation in software development. By embracing the utility of CI/CD pipelines, organizations can ensure that they not only keep pace with market demands but also drive forward with efficiency and precision. As the backbone of modern DevOps practices, the CI/CD pipeline stands as an essential element in the journey towards streamlined, resilient, and customer-centric software delivery.
---
### Continuous Integration - The Backbone of Modern Software Development
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the rapidly evolving landscape of software development, Continuous Integration (CI) has emerged as an essential practice. It represents a fundamental shift in the approach to software building and testing, emphasizing speed, efficiency, and early error detection. Here, we explore the ins and outs of Continuous Integration and its pivotal role in modern software development.
#### What is Continuous Integration?[](#what-is-continuous-integration "Direct link to What is Continuous Integration?")
Continuous Integration is a development practice where developers frequently merge their code changes into a central repository, usually several times a day. After each merge, automated builds and tests are run, ensuring that the new code integrates seamlessly with the existing codebase.
#### The Objectives of Continuous Integration[](#the-objectives-of-continuous-integration "Direct link to The Objectives of Continuous Integration")
* **Early Problem Detection**: Identifying and resolving issues promptly, reducing the risk of compounded problems.
* **Streamlined Development**: Facilitating smoother collaboration and integration among team members.
* **Quality Assurance**: Maintaining a high standard of code quality through automated testing.
* **Reduced Integration Costs**: Lowering the time and resources spent on fixing integration issues.
#### The Continuous Integration Process[](#the-continuous-integration-process "Direct link to The Continuous Integration Process")
* **Commit Code Regularly**: Developers regularly commit small code changes to the central repository.
* **Automated Builds**: Automated systems build the software with each new code commit.
* **Automated Testing**: Running a suite of tests to ensure code quality and functionality.
* **Immediate Feedback**: Providing developers with immediate feedback on the integration process.
* **Rapid Issue Resolution**: Quickly addressing any integration or test failures.
#### Why Continuous Integration is Essential[](#why-continuous-integration-is-essential "Direct link to Why Continuous Integration is Essential")
* **Improved Collaboration**: Encourages more frequent code integration, leading to better team collaboration.
* **Increased Efficiency**: Reduces manual integration efforts, making the development process more efficient.
* **Enhanced Code Quality**: Consistent testing ensures high code quality and reduces bugs in production.
* **Faster Release Cycles**: Accelerates the process from development to deployment, enabling faster release cycles.
#### Challenges in Continuous Integration and Solutions[](#challenges-in-continuous-integration-and-solutions "Direct link to Challenges in Continuous Integration and Solutions")
* **Maintaining Quality with Speed**: Balancing rapid integration with maintaining code quality. Solution: Implement robust automated testing frameworks.
* **Managing Build Failures**: Addressing and preventing frequent build failures. Solution: Enforce coding standards and regular code reviews.
* **Infrastructure Overheads**: Managing the infrastructure required for CI. Solution: Use cloud-based CI tools and services.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Continuous Integration stands as a transformative approach in software development. By automating the integration and testing process, it not only enhances efficiency and quality but also fosters a more collaborative and agile development environment. Embracing Continuous Integration is not just a choice but a necessity for teams aiming to excel in the competitive world of software development.
---
### DevOps Engineer - The Backbone of Efficient Software Deployment
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
The role of a DevOps Engineer has become indispensable. Bridging the gap between software creation and its operational performance, a DevOps Engineer is a key player in the orchestration of code life cycles, ensuring that everything from development to deployment and beyond runs seamlessly. Let’s delve into what makes the DevOps Engineer role so vital.
#### Who is a DevOps Engineer?[](#who-is-a-devops-engineer "Direct link to Who is a DevOps Engineer?")
A DevOps Engineer is a multi-faceted professional who specializes in the development (Dev) and operations (Ops) aspects of software engineering. Their responsibilities extend across the entire development pipeline, focusing on streamlining processes, enhancing performance, and ensuring the reliability of both software and infrastructure.
#### Key Responsibilities of a DevOps Engineer[](#key-responsibilities-of-a-devops-engineer "Direct link to Key Responsibilities of a DevOps Engineer")
* **Development and Maintenance**: Spearheading the development of infrastructure and ensuring its robust maintenance.
* **Deployment**: Orchestrating the deployment process to ensure smooth and timely delivery of software.
* **Monitoring**: Vigilantly monitoring both software and infrastructure to preemptively identify and address issues.
* **Continuous Improvement**: Implementing strategies for continuous development, integration, and deployment.
* **Collaboration**: Acting as a bridge between various teams to foster a cohesive working environment.
#### The Importance of DevOps Engineers[](#the-importance-of-devops-engineers "Direct link to The Importance of DevOps Engineers")
* **Efficiency**: By automating processes and improving communication between development and operations teams, DevOps Engineers significantly enhance efficiency.
* **Agility**: They enable organizations to respond swiftly to market changes and customer demands.
* **Reliability**: Through continuous monitoring and maintenance, they ensure that systems are robust and downtime is minimized.
* **Innovation**: By streamlining workflows, they provide more room for innovation and experimentation.
#### Challenges Faced by DevOps Engineers and Solutions[](#challenges-faced-by-devops-engineers-and-solutions "Direct link to Challenges Faced by DevOps Engineers and Solutions")
* **Complex Workflows**: Handling intricate workflows can be challenging. Solution: Implementation of automation tools and clear communication channels.
* **Rapid Technology Changes**: Keeping pace with ever-evolving technologies. Solution: Continuous learning and adaptation.
* **Balancing Speed and Security**: Ensuring rapid deployment without compromising on security. Solution: Integrating security measures into the development process.
#### Conclusion[](#conclusion "Direct link to Conclusion")
The DevOps Engineer is more than just a role; it’s a mindset that embodies efficiency, collaboration, and continuous improvement. In the current technological era, a proficient DevOps Engineer is not just an asset but a necessity for organizations aiming for resilience, agility, and sustained growth.
---
### Feature Testing - Tailoring the Ultimate User Experience
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
The competitive edge of any software lies in its features — but how do you ensure that each feature resonates with your users? Feature Testing is the answer. It's a strategic approach that enables teams to determine the most impactful version of a feature to deliver a superior user experience. Here's an insight into Feature Testing and its vital role in user-centric development.
#### What is Feature Testing?[](#what-is-feature-testing "Direct link to What is Feature Testing?")
Feature Testing, also known as A/B Testing or Split Testing, is an experimental process where two or more variants of a feature are compared to determine which one performs better in the context of user engagement and satisfaction. It involves exposing your audience to different versions of a feature within your application or website and using data-driven insights to decide which version yields the best outcomes.
#### Objectives of Feature Testing[](#objectives-of-feature-testing "Direct link to Objectives of Feature Testing")
* **User Experience Enhancement**: Refining features to match user expectations and preferences.
* **Performance Measurement**: Quantifying how different feature iterations affect user behavior.
* **Data-Driven Decisions**: Basing feature iterations on concrete analytics rather than guesswork.
* **Conversion Rate Optimization**: Improving the rate at which users take the desired action within the app or site.
#### The Feature Testing Process[](#the-feature-testing-process "Direct link to The Feature Testing Process")
* **Hypothesis Formation**: Begin with a theory or question about how a feature change might impact user behavior.
* **Variant Creation**: Develop multiple versions of the feature in question.
* **Experimentation**: Randomly expose users to different versions and collect data on their interactions.
* **Analysis**: Evaluate the data to determine which version achieved the defined objectives.
#### Why Feature Testing is Indispensable[](#why-feature-testing-is-indispensable "Direct link to Why Feature Testing is Indispensable")
* **Risk Mitigation**: Before a full-scale rollout, test and understand the impact of new features.
* **Improved Retention**: By optimizing features for user satisfaction, increase the likelihood of users sticking around.
* **Agile Development**: Quickly adapt and respond to user feedback, making your development cycle more efficient.
* **Competitive Advantage**: Stay ahead by continuously evolving your product to meet the latest user trends and needs.
#### Challenges in Feature Testing and Strategies to Overcome Them[](#challenges-in-feature-testing-and-strategies-to-overcome-them "Direct link to Challenges in Feature Testing and Strategies to Overcome Them")
* **Statistical Significance**: Ensuring your test results are statistically valid. Strategy: Run tests for adequate durations and with sufficient sample sizes.
* **Bias Elimination**: Preventing the test environment from skewing results. Strategy: Use randomization and control groups effectively.
* **User Segmenting**: Not all users are the same. Strategy: Segment your user base to ensure relevant feedback.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Feature Testing is not just about choosing between 'A' or 'B' — it's about crafting experiences that resonate and retain. It empowers teams to make informed decisions, leading to a product that your users love, every single time. Unlock the potential of every feature and let the data guide your path to success.
---
### Multi-Armed Bandit - Optimizing Decisions in Real-Time
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In an ever-evolving digital landscape, making optimal decisions swiftly can be the difference between success and stagnation. The Multi-Armed Bandit framework embodies this principle, offering a dynamic approach to decision-making that balances the exploration of new opportunities with the exploitation of known strategies. Explore the strategic world of Multi-Armed Bandits, where every choice has the potential to significantly enhance performance and outcomes.
#### What is a Multi-Armed Bandit?[](#what-is-a-multi-armed-bandit "Direct link to What is a Multi-Armed Bandit?")
At its core, the Multi-Armed Bandit (MAB) problem is a scenario in which an agent is faced with several choices, or "arms," each with uncertain rewards. The agent must choose which arm to pull, metaphorically speaking, in a sequence of trials to maximize its total reward over time. This framework is a simplified model of the complex decision-making processes that occur in various fields such as finance, healthcare, online advertising, and more.
#### The Goals of Multi-Armed Bandit Algorithms[](#the-goals-of-multi-armed-bandit-algorithms "Direct link to The Goals of Multi-Armed Bandit Algorithms")
* **Optimal Action Identification**: To discover and exploit the best possible actions that yield the highest rewards.
* **Uncertainty Reduction**: To gather information about the reward distribution of each action.
* **Regret Minimization**: To minimize the difference between the rewards received and the rewards that could have been received by always choosing the best action.
#### The Multi-Armed Bandit Process[](#the-multi-armed-bandit-process "Direct link to The Multi-Armed Bandit Process")
* **Trial and Error**: The agent tests different arms to gather data on their performance.
* **Reward Assessment**: After each trial, the agent assesses the reward from the chosen arm.
* **Strategy Adaptation**: Based on accumulated knowledge, the agent refines its selection strategy.
* **Continuous Learning**: The process is iterative, allowing continuous learning and adaptation to changing environments.
#### Why Multi-Armed Bandit is Essential[](#why-multi-armed-bandit-is-essential "Direct link to Why Multi-Armed Bandit is Essential")
* **Real-Time Decision Making**: MAB algorithms provide a framework for making decisions on-the-fly in real-time environments.
* **Resource Efficiency**: They help allocate limited resources to the most effective strategies.
* **Adaptability**: MABs are robust to changes and can quickly adjust strategies based on new data.
* **Experimental Efficiency**: They are crucial in A/B testing scenarios where rapid learning is essential.
#### Challenges in Multi-Armed Bandit Implementations and Solutions[](#challenges-in-multi-armed-bandit-implementations-and-solutions "Direct link to Challenges in Multi-Armed Bandit Implementations and Solutions")
* **Exploration vs. Exploitation Dilemma**: Balancing the need to explore new actions with the need to exploit known high-reward actions. Solution: Employ algorithms like epsilon-greedy, UCB (Upper Confidence Bound), or Thompson Sampling to manage this trade-off effectively.
* **Dynamic Environments**: Adapting to environments where reward distributions change over time. Solution: Use non-stationary MAB algorithms that adjust to trends and volatility.
* **Complex Reward Structures**: Dealing with scenarios where rewards are not immediate or straightforward. Solution: Develop MAB models that can handle delayed feedback and complex reward mechanisms.
#### Conclusion[](#conclusion "Direct link to Conclusion")
The Multi-Armed Bandit framework is a powerful tool in the modern decision-maker's arsenal, allowing for smarter, data-driven choices that evolve with experience. Whether it's optimizing click-through rates in digital marketing or determining treatment plans in clinical trials, MABs offer a structured yet flexible approach to navigating the uncertainties inherent in decision-making processes. As we continue to harness the potential of these algorithms, the ceiling for innovation and efficiency rises ever higher.
---
### Product Lifecycle Manager – Steering Projects to Success
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the dynamic world of product development, the trajectory from an idea to a market-ready product is intricate and layered with challenges. A Product Lifecycle Manager is the maestro of this journey, synchronizing each movement to create a symphony of efficiency and success. Dive into the role of these pivotal professionals and how they are integral to a product's evolution.
#### Who is a Product Lifecycle Manager?[](#who-is-a-product-lifecycle-manager "Direct link to Who is a Product Lifecycle Manager?")
A Product Lifecycle Manager is a strategic orchestrator responsible for overseeing the progression of a product through its lifecycle. They are the guardians of the project timeline, ensuring that every stage, from conception to release, adheres to the planned schedule and quality standards.
#### Responsibilities of a Product Lifecycle Manager[](#responsibilities-of-a-product-lifecycle-manager "Direct link to Responsibilities of a Product Lifecycle Manager")
* **Strategic Planning**: Crafting a comprehensive plan that outlines each stage of the product's lifecycle.
* **Team Coordination**: Leading and motivating the project team to achieve the set objectives.
* **Milestone Tracking**: Monitoring the progress and ensuring that key deliverables are met on time.
* **Quality Assurance**: Upholding the highest standards of quality at each phase of the product's development.
* **Risk Management**: Identifying potential issues and implementing strategies to mitigate risks.
#### The Lifecycle of a Product[](#the-lifecycle-of-a-product "Direct link to The Lifecycle of a Product")
* **Conceptualization**: Ideation and initial planning of the product's vision.
* **Development**: Transforming the concept into a tangible prototype or early version.
* **Testing**: Rigorous evaluation to refine the product and prepare it for market.
* **Launch**: Introducing the product to the market with strategic marketing and distribution.
* **Evaluation**: Analyzing the product's performance and gathering feedback for improvement.
#### The Impact of a Product Lifecycle Manager[](#the-impact-of-a-product-lifecycle-manager "Direct link to The Impact of a Product Lifecycle Manager")
* **Project Efficiency**: Streamlining processes to minimize waste and optimize resources.
* **Timely Delivery**: Ensuring that products are developed and launched within the expected timelines.
* **Market Relevance**: Keeping the product aligned with market needs and consumer expectations.
* **Continuous Improvement**: Leveraging feedback for ongoing product enhancement and evolution.
#### Conclusion[](#conclusion "Direct link to Conclusion")
The role of a Product Lifecycle Manager is indispensable in navigating the complex waters of product development. With their expertise, products don't just reach completion; they do so with a competitive edge and in alignment with market demands. They ensure that the lifecycle of a project is not just a passage of time but a curated path towards excellence.
---
### Release Manager – Orchestrating Successful Software Deployments
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
The Release Manager plays a crucial role, choreographing the movements between coding and client delivery. Gain insights on the multifaceted responsibilities of a Release Manager and the importance of this role in the IT industry.
#### Who is a Release Manager?[](#who-is-a-release-manager "Direct link to Who is a Release Manager?")
A Release Manager is a professional within the IT realm, tasked with overseeing the software release lifecycle from development to deployment. Their goal is to ensure that every software release is executed efficiently, meets quality standards, and is delivered on schedule.
#### The Role of a Release Manager[](#the-role-of-a-release-manager "Direct link to The Role of a Release Manager")
* **Process Definition**: Creating and refining the release management process to align with business goals.
* **Coordination and Planning**: Orchestrating the efforts of development, operations, and quality assurance teams to ensure a harmonious release process.
* **Quality Assurance**: Certifying that each release meets the necessary quality thresholds before it reaches customers.
* **Risk Management**: Identifying potential issues in the release process and mitigating them to prevent delays or failures.
#### Key Responsibilities[](#key-responsibilities "Direct link to Key Responsibilities")
* **Release Planning**: Crafting a detailed release schedule and ensuring all teams adhere to it.
* **Change Management**: Supervising the change process to maintain stability and integrity of the product.
* **Deployment**: Overseeing the final stages of the release, including the deployment strategy and execution.
* **Post-Release Support**: Ensuring support systems are in place for post-deployment issues and feedback.
#### Why a Release Manager is Indispensable[](#why-a-release-manager-is-indispensable "Direct link to Why a Release Manager is Indispensable")
* **Streamlined Deployments**: A Release Manager irons out any issues in the deployment process, making it as efficient as possible
* **Quality Control**: Their oversight helps maintain the high standards expected of modern software releases.
* **Communication Hub**: Acting as the central point of communication, they keep all stakeholders informed and coordinated.
#### Challenges and Strategies[](#challenges-and-strategies "Direct link to Challenges and Strategies")
* **Managing Diverse Teams**: A Release Manager often navigates varied team dynamics. Strategy: Clear communication and strong leadership skills are key.
* **Adapting to Change**: With technology evolving rapidly, release managers must be agile. Strategy: Continuous learning and adaptation to new tools and practices.
* **Ensuring Security**: Security concerns are paramount. Strategy: Implementing thorough security checks and balances within the release process.
#### Conclusion[](#conclusion "Direct link to Conclusion")
The Release Manager is the unsung hero ensuring that software deployments are successful and seamless. In a world where software is integral to business success, the role of a Release Manager cannot be overstated. They ensure that new features reach users smoothly, securely, and without disrupting the service – a true linchpin in the software development cycle.
---
### Remote Configuration - Agile Adjustments at Your Fingertips
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In the dynamic world of software development, the ability to make quick adjustments to live applications is a game-changer. Remote configuration is the magic wand that enables developers and product teams to update features or settings of an app in real-time, without rolling out a new version. Dive into the flexibility and control offered by remote configuration and how it can be a critical tool for your app’s success.
#### What is Remote Configuration?[](#what-is-remote-configuration "Direct link to What is Remote Configuration?")
Remote configuration allows teams to seamlessly modify an application's functionality and user interface without rolling out a new version or update. This approach provides the agility to adapt features or address problems instantly, keeping the application adaptive and user-centric at all times
#### The Power of Remote Configuration[](#the-power-of-remote-configuration "Direct link to The Power of Remote Configuration")
* **Rapid Changes**: Implement feature toggles or turn features on and off quickly.
* **User Experience Customization**: Personalize content and features for different user segments in real-time.
* **A/B Testing**: Test out new features with selected user groups before a wide release to gather data and feedback.
* **Issue Mitigation**: Quickly respond to unforeseen bugs or issues by remotely adjusting app settings.
#### Implementing Remote Configuration[](#implementing-remote-configuration "Direct link to Implementing Remote Configuration")
* **Integration**: Setting up remote configuration starts with integrating a remote configuration service or platform with your app.
* **Control Panel**: Use a dashboard to manage the configurations that control various features of your app.
* **Monitoring**: Keep an eye on how changes affect app performance and user experience with real-time monitoring tools.
#### Why Remote Configuration is a Staple for Modern Apps[](#why-remote-configuration-is-a-staple-for-modern-apps "Direct link to Why Remote Configuration is a Staple for Modern Apps")
* **Agility**: Update your app on-the-go to keep up with rapidly changing market demands.
* **Cost-Effectiveness**: Save on resources by reducing the number of deployments.
* **User Retention**: Improve user retention by quickly adapting to user feedback and market trends.
* **Reduced Risk**: Test changes with a small percentage of your user base to reduce the risk of negative impact.
#### Challenges and Best Practices[](#challenges-and-best-practices "Direct link to Challenges and Best Practices")
* **Overuse**: Avoid confusion by not overdoing the frequency and volume of changes.
* **User Feedback**: Implement mechanisms to gather user feedback after making changes.
* **Documentation**: Keep detailed logs of changes to track the impact and revert if necessary.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Remote configuration stands out as an essential feature in the arsenal of modern software development. By incorporating remote configuration techniques, developers can ensure that their applications are as adaptable as they are robust, providing the best possible experience for the end-user with minimal disruption.
---
### Smoke Testing - Ensuring the Core of Your Software Stands Strong
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
Smoke testing acts as a preliminary check to confirm that the key features of an application are working effectively. Delve into the fundamentals of smoke testing and its critical role in the early stages of the development cycle.
#### What is Smoke Testing?[](#what-is-smoke-testing "Direct link to What is Smoke Testing?")
Smoke testing, often known as "build verification testing," is a shallow and wide approach to testing that evaluates whether the most fundamental functions of an application operate without any critical issues. It's like doing an initial health check-up for software.
#### The Aims of Smoke Testing[](#the-aims-of-smoke-testing "Direct link to The Aims of Smoke Testing")
* **Critical Feature Check**: Ensuring that the primary functions perform correctly.
* **Build Stability**: Validating the stability of initial software builds.
* **Early Problem Detection**: Catching severe issues at the onset before they propagate.
#### The Smoke Testing Cycle[](#the-smoke-testing-cycle "Direct link to The Smoke Testing Cycle")
* **Build**: The latest version of the application is prepared for testing.
* **Deploy**: The build is placed in a testing environment similar to production.
* **Test**: Core functionalities are tested to ensure they work as expected.
* **Report**: Results are documented, with failures addressed immediately.
#### The Importance of Smoke Testing[](#the-importance-of-smoke-testing "Direct link to The Importance of Smoke Testing")
* **Saves Time**: Identifies major problems early, avoiding wasted effort on flawed builds.
* **Enhances Quality**: Promotes a more stable and reliable software development process.
* **Facilitates Continuous Integration**: Acts as a checkpoint for new integrations and deployments.
#### Challenges in Smoke Testing and Overcoming Them[](#challenges-in-smoke-testing-and-overcoming-them "Direct link to Challenges in Smoke Testing and Overcoming Them")
* **Scope Definition**: Determining what constitutes the 'smoke' can be subjective. Solution: Develop clear criteria for essential features.
* **Environment Differences**: Discrepancies between testing and production environments can skew results. Solution: Mirror production settings as closely as possible.
* **Automation Balance**: Deciding what to automate versus what to manually test. Solution: Automate common and stable features; manually test newly added features.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Smoke testing serves as the first line of defense, ensuring that the application's backbone is robust before it's subject to detailed testing. By verifying the core functionality after each build, developers can proceed with confidence, knowing that the foundation of their application is solid.
---
### Navigating Type I & Type II Errors in Software Testing
Copy page
#### Exploring Type I and Type II Errors in Software Testing[](#exploring-type-i-and-type-ii-errors-in-software-testing "Direct link to Exploring Type I and Type II Errors in Software Testing")
In the intricate process of software development, testing stands as a guardian of quality, ensuring that applications perform as expected. Type I and Type II errors represent critical checkpoints in software testing, influencing the effectiveness of identifying true software defects.
##### Understanding Type I and Type II Errors in Software[](#understanding-type-i-and-type-ii-errors-in-software "Direct link to Understanding Type I and Type II Errors in Software")
* **Type I Error (False Positive)**: Occurs when a software test incorrectly flags a function as failing, despite it working as intended.
* **Type II Error (False Negative)**: Happens when a test overlooks an actual flaw in the software, falsely indicating that everything is functioning properly.
##### The Significance for Software Quality[](#the-significance-for-software-quality "Direct link to The Significance for Software Quality")
* **Type I Error Consequences**: Although false positives can be time-consuming, they are typically less detrimental than Type II errors as they rarely allow defects to go unnoticed.
* **Type II Error Consequences**: False negatives are more critical as they can lead to faulty software being released, which can compromise functionality and user trust.
##### Strategies for Reducing Error Risks[](#strategies-for-reducing-error-risks "Direct link to Strategies for Reducing Error Risks")
Effective strategies to reduce the risk of these errors in software testing include:
* **Enhanced Test Coverage**: Broadening the scope of testing to cover more features and use cases.
* **Automated and Manual Testing**: Leveraging both automated and manual testing approaches to complement each other.
* **Continuous Testing in CI/CD**: Integrating continuous testing in the development pipeline to catch issues early.
* **Real-world User Scenarios**: Incorporating real user testing to identify problems that might not be evident in controlled test environments.
##### Conclusion[](#conclusion "Direct link to Conclusion")
Acknowledging and addressing Type I and Type II errors is a cornerstone of a quality-driven development process. It sharpens the focus on delivering software that not only meets the functional requirements but also upholds the highest standards of reliability.
---
### Version Control - The Backbone of Successful Software Development
Copy page
#### Introduction[](#introduction "Direct link to Introduction")
In software development, version control is a crucial tool that keeps track of every modification to the code. With version control, developers can easily coordinate updates, prevent conflicts, and ensure that all changes are accurately recorded. This system acts as a historical archive, allowing developers to see past versions of their work and plan future updates. It's an essential part of managing and maintaining a clean and efficient codebase.
#### What is Version Control?[](#what-is-version-control "Direct link to What is Version Control?")
Version control, at its essence, is the practice of tracking and managing changes to software code. It's a system that records changes to a file or set of files over time so that specific versions can be recalled later on. This becomes especially critical as projects grow in complexity and size.
#### The Objectives of Version Control[](#the-objectives-of-version-control "Direct link to The Objectives of Version Control")
* **Change Tracking**: Keeping a detailed record of who changed what, and when.
* **Collaboration**: Coordinating smoothly among teams, especially when multiple people work on the same files.
* **Backup & Restore**: Saving work and recovering from unintended changes or errors.
* **Branching & Merging**: Developing features in parallel and combining changes from different contributors.
#### The Version Control Process[](#the-version-control-process "Direct link to The Version Control Process")
* **Committing Changes**: Developers make changes to their code and then "commit" these changes, which records them in the version control system.
* **Updating**: Synchronizing the local work with the shared repository to keep current with others' work.
* **Branching**: Creating branches allows teams to work on new features without disrupting the main codebase.
* **Merging**: Combining different code branches back into the main branch to unify the codebase.
#### Why Version Control is Essential[](#why-version-control-is-essential "Direct link to Why Version Control is Essential")
* **History and Audit Trail**: A complete log of the changes, comments, and decision-making process.
* **Recovery**: The ability to revert back to previous versions if something goes wrong.
* **Parallel Development**: Multiple streams of work can happen simultaneously without conflict.
* **Accountability**: Clear accountability for each change made in the project.
#### Challenges in Version Control[](#challenges-in-version-control "Direct link to Challenges in Version Control")
* **Merge Conflicts**: Can occur when changes in one branch are incompatible with those in another. **Solution**: Regular merges and automated testing can identify conflicts early.
* **Learning Curve**: Version control systems can be complex. **Solution**: Training and the use of intuitive tools can ease the learning process.
* **Repository Bloat**: Over time, the repository can become unwieldy. **Solution**: Good housekeeping practices, like pruning old branches, can keep the repository clean.
#### Conclusion[](#conclusion "Direct link to Conclusion")
Version control is more than just a tool; it's a foundational practice that supports the complexities and collaborative nature of software development. It's a powerful ally in the developer's quest to build robust, error-free software, making it a pillar of any development team's toolbox. With version control, we chart the past and present, giving us the power to foresee and shape the future of our projects.
---
### What Is a Staging Environment?
Copy page
When you’re in the process of deploying new code, the possibility that bad code could throw off your rollout and render the whole project a failure may always be at the forefront of your mind.
A staging environment is a natural solution to this problem, allowing you to ensure your code is in tip-top shape before it is deployed.
In this article, we’ll explore:
* What a staging environment is, and why it’s important.
* The various components of a staging environment.
* Different types of testing that can be conducted.
* Best practices and potential challenges with staging environments.
#### What Is a Staging Environment?[](#what-is-a-staging-environment "Direct link to What Is a Staging Environment?")
A staging environment is a dry run for your code under the closest possible parameters to its real-world application. It is a near-perfect replica of the servers, infrastructure, architecture, and application of the actual use environment of your code. The key difference is that it is completely walled off from the front-facing actual environment.
#### Components of a Staging Environment[](#components-of-a-staging-environment "Direct link to Components of a Staging Environment")
While a staging environment is a means of testing code, it is distinct from a testing environment as it uses a complete replica setup to test the code in a variety of different, simultaneous ways that would be present in actual applications. To that end, staging environments are made up of a variety of components you wouldn’t find in a test environment.
##### Hardware and Infrastructure[](#hardware-and-infrastructure "Direct link to Hardware and Infrastructure")
A staging environment must run as similarly as possible to the code’s intended environment. Because of this requirement, the hardware and infrastructure of your staging environment need to match the hardware and infrastructure of that intended environment in order to test the code in circumstances as close to real-world as possible.
###### Staging Environment vs. Production Environment[](#staging-environment-vs-production-environment "Direct link to Staging Environment vs. Production Environment")
The production environment refers to new code that is made live and put in front of its intended users – the final stage of the production life cycle. Since a staging environment runs on the exact same hardware and infrastructure and is subject to the same technical stresses as the production environment, the key difference is the lack of real users.
##### Data in Staging[](#data-in-staging "Direct link to Data in Staging")
The purpose of a staging environment is to collect as much data as possible on the performance and stresses on code before it gets in front of users. The more data you can collect and assess, the better equipped you are to find issues and resolve them before your product goes live.
#### The Importance of a Staging Environment[](#the-importance-of-a-staging-environment "Direct link to The Importance of a Staging Environment")
We can see how a staging environment that is set up well and part of a robust testing schedule is a fundamental step in getting new code user-ready. However, what are the key benefits a staging environment offers?
##### Catching Bugs Early[](#catching-bugs-early "Direct link to Catching Bugs Early")
Buggy code can be an absolute disaster, and the worst-case scenario is a catastrophic issue being discovered after deployment to the intended users. Obviously, having an environment in which you can put code under the pressures of the actual hardware and architecture it has to run on has a lot of benefits in catching bugs early.
##### Testing New Features[](#testing-new-features "Direct link to Testing New Features")
Rolling out new code could mean a completely new product built from the ground up. It could also mean adding new functionality to existing code. A staging environment allows you to test how new features interact with the pre-existing product and develop solutions to any incompatibilities before they go live.
##### Preparing for Scalability[](#preparing-for-scalability "Direct link to Preparing for Scalability")
If you imagine a staging environment as a model of your real-world coding environment, then using it as an opportunity to see how your code behaves as you scale it up across multiple platforms or applications is a key feature of the process.
#### Types of Testing in a Staging Environment[](#types-of-testing-in-a-staging-environment "Direct link to Types of Testing in a Staging Environment")
A staging environment offers a lot of different opportunities to test a range of features and capabilities of your code. Some are simple tests that will be clear as soon as you deploy the product to your staging environment, while others require a direct effort to test.
##### Integration Testing[](#integration-testing "Direct link to Integration Testing")
Integration testing is the process of introducing successive pieces of software into an environment and eventually testing how they function in concert with one another. Introducing code systematically into a staging environment allows you to assess how it will operate within existing systems.
##### User Acceptance Testing[](#user-acceptance-testing "Direct link to User Acceptance Testing")
User acceptance testing is a process where software is tested by its intended users. This can take the form of in-house volunteers, developers playing the role of the end-user, or paid test subjects. In any case, user acceptance testing should be carried out in a staging environment to put your code through its paces under realistic conditions.
##### Performance & Load Testing[](#performance--load-testing "Direct link to Performance & Load Testing")
The first thing you’ll likely think of when you think of testing your product is performance or load testing. These are the classic tests: How well does the code do what it’s supposed to do? How does it handle multiple requests? How does it handle rapid spikes in use? These tests are all instrumental in determining how your product will cope with day-to-day use.
##### Security Testing[](#security-testing "Direct link to Security Testing")
Security testing in a staging environment gives you the chance to test security features without actually putting any important data or accesses out in the open. This is obviously a good idea if your code deals with sensitive information, but a crucial step for any software or coding product.
##### Regression Testing[](#regression-testing "Direct link to Regression Testing")
Regression testing helps ensure no old bugs raise their ugly head with the introduction of new code. This occasional problem is better assessed and dealt with in a staging environment rather than leaving end users to discover it.
#### Best Practices for Effective Staging[](#best-practices-for-effective-staging "Direct link to Best Practices for Effective Staging")
##### Continuous Integration and Delivery[](#continuous-integration-and-delivery "Direct link to Continuous Integration and Delivery")
A staging environment is an excellent system for managing continuous integration and delivery. This increases efficiency and reliability of code implementation.
##### Regular Testing and Monitoring[](#regular-testing-and-monitoring "Direct link to Regular Testing and Monitoring")
Regular testing and monitoring in a staging environment for each and every new deployment or update keep your project running smoothly without any hiccups. Be sure to devote appropriate time to running multiple tests and reviewing the accompanying data.
##### Testing and Debugging[](#testing-and-debugging "Direct link to Testing and Debugging")
Ensure you run your debugging before the product goes live. The staging environment gives you the best setting in which to perform debugging and testing, and it prepares you for real-world debugging requirements.
#### Potential Challenges with Staging Environments[](#potential-challenges-with-staging-environments "Direct link to Potential Challenges with Staging Environments")
While staging environments are an integral tool in any development process, there are a handful of challenges you need to be aware of when implementing this stage of development. These challenges include:
* Data synchronization and drift challenges
* Resource limitations and contention
* Configuration discrepancies and version control
* Delayed bug detection and testing scalability
* Security vulnerabilities and collaboration bottlenecks.
Understanding how these challenges can arise and experimenting within the staging environment to find solutions to them is a normal part of the staging environment process, and is worth investing time and effort into before the product goes live.
#### A Handy Tool in the Development Process: Closing Thoughts[](#a-handy-tool-in-the-development-process-closing-thoughts "Direct link to A Handy Tool in the Development Process: Closing Thoughts")
As we’ve covered, a staging environment is a handy tool in the development process of any coding project. It gives you the flexibility to experiment with solutions, the opportunity to prepare for potential bugs, and the best chance of success by working in a similar environment to your final product. Taking advantage of the value that a staging environment brings will make your project rollout smoother, more efficient, and the highest quality it can be.
---
## Advanced Guides
### Polling modes & Caching
Copy page
There are 3 different ways (polling modes) to control caching.
#### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
In auto polling mode, the ConfigCat SDK downloads the latest feature flags and settings from the ConfigCat CDN automatically and stores them in the cache. By default, this happens every 60 seconds. You can set the polling interval to any value between 1 and 2,147,483 seconds.
#### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
In lazy loading mode, the ConfigCat SDK downloads the latest feature flags and settings from the ConfigCat CDN only if they are not already present in the cache, or if the cache has expired. By default, the cache Time To Live (TTL) value is 60 seconds. You can set it to any value between 1 and 2,147,483,647 seconds.
#### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the feature flags and settings are downloaded from the ConfigCat CDN. The ConfigCat SDK will not download them automatically. You can (and should) update the cache manually, by calling a `forceRefresh()` - this will download the latest feature flags and settings and update the cache.
This animation explains the different polling modes:
#### Caching[](#caching "Direct link to Caching")
ConfigCat SDKs in their default setup store all the information they need for feature flag evaluation in memory. This behavior is extendable with custom cache implementations that you can use for pointing the SDK to your own data storage.
The main reason for caching is to accelerate serving feature flag evaluation requests when your application is in a stateless environment or frequently restarts. When the SDK notices that it has a valid cache entry to work with, it will use the data from the cache rather than initiating a new HTTP request towards ConfigCat. The cache's validity is based on the polling interval in case of [auto polling](#auto-polling-default) or on the TTL in case of [lazy loading](#lazy-loading).
info
See the [SDK specific docs](https://configcat.com/docs/sdk-reference/overview.md) for your desired platform to learn how to use custom cache implementations.
##### Offline mode[](#offline-mode "Direct link to Offline mode")
ConfigCat SDKs have the capability to go offline. In offline mode, they work only from the configured cache and never communicate with ConfigCat over HTTP.
This allows you to set up a centralized cache that only one online ConfigCat SDK writes, but serves many offline ones.
info
See the [SDK specific docs](https://configcat.com/docs/sdk-reference/overview.md) for your desired platform to learn how to enable offline mode.
##### Shared cache[](#shared-cache "Direct link to Shared cache")
As of certain versions, ConfigCat SDKs support using a shared cache. To achieve that, each SDK constructs the key for identifying a specific cache entry based on the SDK key passed at initialization. This means each platform specific SDK that uses the same SDK key will use the same cache entry.
Mixing this behavior with [offline mode](#offline-mode), you can have a centralized shared cache that serves many SDKs regardless of what platform they run on.
Support for shared caching was introduced in these SDK versions:
| SDK | Version |
| ------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| .NET | >= [v8.1.0](https://github.com/configcat/.net-sdk/releases) |
| Android (Java) | >= [v9.0.0](https://github.com/configcat/android-sdk/releases) |
| C++ | >= [v3.0.0](https://github.com/configcat/cpp-sdk/releases) |
| Dart (Flutter) | >= [v3.0.0](https://github.com/configcat/dart-sdk/releases) |
| Elixir | >= [v3.0.0](https://github.com/configcat/elixir-sdk/releases) |
| Go | >= [v8.0.0](https://github.com/configcat/go-sdk/releases) |
| Java | >= [v8.2.0](https://github.com/configcat/java-sdk/releases) |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node.js) | >= [v1.0.0](https://github.com/configcat/js-unified-sdk/releases) |
| JS - Legacy | >= [v8.0.0](https://github.com/configcat/js-sdk/releases) |
| JS SSR - Legacy | >= [v7.0.0](https://github.com/configcat/js-ssr-sdk/releases) |
| Kotlin | >= [v2.0.0](https://github.com/configcat/kotlin-sdk/releases) |
| Node.js - Legacy | >= [v10.0.0](https://github.com/configcat/node-sdk/releases) |
| PHP | >= [v8.0.0](https://github.com/configcat/php-sdk/releases) |
| Python | >= [v8.0.0](https://github.com/configcat/python-sdk/releases) |
| React | >= [v3.0.0](https://github.com/configcat/react-sdk/releases) |
| Ruby | >= [v7.0.0](https://github.com/configcat/ruby-sdk/releases) |
| Rust | >= [v0.1.0](https://github.com/configcat/rust-sdk/releases) |
| Swift (iOS) | >= [v10.0.0](https://github.com/configcat/swift-sdk/releases) |
---
### Command Line Interface (CLI)
Copy page
The [ConfigCat Command Line Interface (CLI)](https://github.com/configcat/cli) allows you to interact with the [Public Management API](https://configcat.com/docs/api/reference/configcat-public-management-api.md) via the command line. It supports most functionality found on the ConfigCat Dashboard. You can manage ConfigCat resources like Feature Flags, Targeting / Percentage rules, Products, Configs, Environments, and more.
The CLI also has the ability to [scan your source code](https://configcat.com/docs/advanced/code-references/overview.md) for feature flag and setting usage and upload the found code references to ConfigCat.
Finally, the CLI provides a few useful utilities, such as validating a config JSON file, downloading one from the ConfigCat CDN by SDK Key, etc. These can come in handy when you use [flag overrides](https://configcat.com/docs/sdk-reference/js/overview.md#flag-overrides) in your application.
```text
configcat
This is the Command Line Tool of ConfigCat.
ConfigCat is a hosted feature flag service: https://configcat.com
For more information, see the documentation here: https://configcat.com/docs/advanced/cli
Usage:
configcat [command] [options]
Options:
-v, --verbose Print detailed execution information
-ni, --non-interactive Turn off progress rendering and interactive features
--version Show version information
-?, -h, --help Show help and usage information
Commands:
setup Setup the CLI with Public Management API host and credentials
ls List all Product, Config, and Environment IDs
p, product Manage Products
c, config Manage Configs
webhook, wh Manage Webhooks
e, environment Manage Environments
f, flag, s, setting Manage Feature Flags & Settings
f2, flag-v2, s2, setting-v2 Manage V2 Feature Flags & Settings
seg, segment Manage Segments
permission-group, pg Manage Permission Groups
m, member Manage Members
t, tag Manage Tags
k, sdk-key List SDK Keys
scan Scan files for Feature Flag & Setting usages
eval Evaluate feature flags. In case of a single feature flag, by default, the command
writes only the evaluated value to the output. In case of multiple feature flags, the
command writes a table if no other format is specified
config-json Config JSON-related utilities
w, workspace Manage the CLI workspace. When set, the CLI's interactive mode filters Product and
Config selectors by the values set in the workspace
Use "configcat [command] -?" for more information about a command.
```
#### Reference[](#reference "Direct link to Reference")
See the [command reference documentation](https://configcat.github.io/cli/) for more information about each available command.
#### Getting started[](#getting-started "Direct link to Getting started")
The following instructions will guide you through the first steps to start using this tool.
##### Installation[](#installation "Direct link to Installation")
You can install the CLI on multiple operating systems using the following sources.
**Homebrew (macOS / Linux)**
Install the CLI with [Homebrew](https://brew.sh) from [ConfigCat's tap](https://github.com/configcat/homebrew-tap) by executing the following command:
```bash
brew tap configcat/tap
brew install configcat
```
**Snap (Linux)**
Install the CLI with [Snapcraft](https://snapcraft.io) by executing the following command:
```bash
sudo snap install configcat
```
**Scoop (Windows)**
Install the CLI with [Scoop](https://scoop.sh) from [ConfigCat's bucket](https://github.com/configcat/scoop-configcat) by executing the following command:
```bash
scoop bucket add configcat https://github.com/configcat/scoop-configcat
scoop install configcat
```
**Chocolatey (Windows)**
Install the CLI with [Chocolatey](https://chocolatey.org/) by executing the following command:
```powershell
choco install configcat
```
**.NET tool / NuGet.org**
The CLI can be installed as a [.NET tool](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) via the .NET SDK.
```bash
dotnet tool install -g configcat-cli
```
After installing, you can execute the CLI using the `configcat` command:
```bash
configcat scan "/repository" --print --config-id
```
**Docker**
The CLI can be executed from a [Docker](https://www.docker.com/) image.
```bash
docker pull configcat/cli
```
An example of how to scan a repository for feature flag & setting references with the docker image.
```bash
docker run --rm \
--env CONFIGCAT_API_HOST= \
--env CONFIGCAT_API_USER= \
--env CONFIGCAT_API_PASS= \
-v /path/to/repository:/repository \
configcat/cli scan "/repository" --print --config-id
```
**Install Script**
On Unix platforms, you can install the CLI by executing an install script.
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash
```
By default, the script downloads the OS specific artifact from the latest [GitHub Release](https://github.com/configcat/cli/releases) with `curl` and moves it into the `/usr/local/bin` directory.
It might happen that you don't have permissions to write into `/usr/local/bin`, then you should execute the install script with `sudo`.
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | sudo bash
```
The script accepts the following input parameters:
| Parameter | Description | Default value |
| ----------------- | ------------------------------------------------ | ---------------- |
| `-d`, `--dir` | The directory where the CLI should be installed. | `/usr/local/bin` |
| `-v`, `--version` | The desired version to install. | `latest` |
| `-a`, `--arch` | The desired architecture to install. | `x64` |
Available **architecture** values for Linux: `x64`, `musl-x64`, `arm`, `arm64`.
Available **architecture** values for macOS: `x64`, `arm64`.
**Script usage examples**:
*Custom installation directory*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -d=/path/to/install
```
*Install a different version*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -v=1.4.2
```
*Install with custom architecture*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -a=arm
```
**Standalone executables**
You can download the executables directly from [GitHub Releases](https://github.com/configcat/cli/releases) for your desired platform.
##### Setup[](#setup "Direct link to Setup")
After a successful installation, the CLI must be set up with your [ConfigCat Public Management API credentials](https://app.configcat.com/my-account/public-api-credentials).
You can do this by using the `configcat setup` command.

###### Environment variables[](#environment-variables "Direct link to Environment variables")
Besides the `setup` command above, the CLI can read your credentials from the following environment variables.
| Name | Description |
| -------------------- | ---------------------------------------- |
| `CONFIGCAT_API_HOST` | API host (default: `api.configcat.com`). |
| `CONFIGCAT_API_USER` | API basic auth user name. |
| `CONFIGCAT_API_PASS` | API basic auth password. |
caution
When any of these environment variables are set, the CLI will use them over the local values set by the `configcat setup` command.
#### Modes[](#modes "Direct link to Modes")
The CLI supports both interactive and argument driven execution. When no arguments provided for a command and user input is enabled (stdout is not redirected), the CLI automatically activates interactive mode.
##### Interactive[](#interactive "Direct link to Interactive")

##### With arguments[](#with-arguments "Direct link to With arguments")
The same operation with command arguments would look like this:
```bash
configcat flag-v2 create \
--config-id \
--name "My awesome feature" \
--hint "This is my awesome feature" \
--key my_awesome_feature
--type boolean \
--tag-ids \
--init-values-per-environment : \
```
info
Each `create` command writes the newly created resource's ID to the standard output so you can save that for further operations.
Example:
```bash
#!/bin/bash
ORGANIZATION_ID=""
PRODUCT_ID=$(configcat product create -o $ORGANIZATION_ID -n "")
CONFIG_ID=$(configcat config create -p $PRODUCT_ID -n "")
```
info
You can change the output format of several commands' result to JSON with the `--json` option, like: `configcat flag ls --json`. See more about these commands in the [command reference documentation](https://configcat.github.io/cli/).
#### Scan & upload code references[](#scan--upload-code-references "Direct link to Scan & upload code references")
The CLI has the ability to scan your source code for feature flag and setting usage and upload the found code references to ConfigCat. You can read more about this feature [here](https://configcat.com/docs/advanced/code-references/overview.md).
#### Examples[](#examples "Direct link to Examples")
Here are a few examples showing the true power of the CLI.
##### Create a feature flag[](#create-a-feature-flag "Direct link to Create a feature flag")
The following example shows how you can create a feature flag in a specific config.

##### Evaluate feature flags[](#evaluate-feature-flags "Direct link to Evaluate feature flags")
The following example shows how you can evaluate one or more feature flags.

##### Feature flag value update[](#feature-flag-value-update "Direct link to Feature flag value update")
The following example shows how you can update the value of a feature flag in a specific environment.

##### Add targeting rules[](#add-targeting-rules "Direct link to Add targeting rules")
The following example shows how you can add targeting rules to a feature flag.

##### Add percentage options[](#add-percentage-options "Direct link to Add percentage options")
The following example shows how you can set percentage options in a feature flag.

---
### Azure DevOps - Scan your source code for feature flags
Copy page
This section describes how to use the [ConfigCat CLI](https://configcat.com/docs/advanced/cli.md) in [Azure DevOps Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in Azure DevOps [Pipeline Variables](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new or open your existing `azure-pipelines.yml` file, and add the following [job](https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema#job) to your `jobs` definition. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- job: configcat_scan_and_upload
container: configcat/cli:azure-devops-2.4.2
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
persistCredentials: true
- script: configcat scan $(Build.Repository.LocalPath)
--config-id=PASTE-YOUR-CONFIG-ID-HERE
--repo=$(Build.Repository.Name)
--branch=$(Build.SourceBranchName)
--file-url-template="$(Build.Repository.Uri)?path={filePath}&version=GC{commitHash}&line={lineNumber}&lineStartColumn=1&lineEndColumn=1"
--commit-url-template="$(Build.Repository.Uri)/commit/{commitHash}"
--runner="ConfigCat Azure DevOps Job"
--upload
--non-interactive
name: scan_repository
env:
CONFIGCAT_API_PASS: $(CONFIGCAT_API_PASS)
CONFIGCAT_API_USER: $(CONFIGCAT_API_USER)
```
info
If you are using a different VCS than Azure DevOps' Git, you should set the `--file-url-template` and `--commit-url-template` according to your VCS provider.
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
---
### Bitbucket Pipe - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [Bitbucket Pipe](https://bitbucket.org/product/features/pipelines/integrations?p=configcat/scan-repository-pipe) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about Bitbucket Pipelines [here](https://bitbucket.org/product/features/pipelines).
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following snippet to the script section of your `bitbucket-pipelines.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- pipe: configcat/scan-repository-pipe:1.8.1
variables:
CONFIG_ID: 'PASTE-YOUR-CONFIG-ID-HERE'
# LINE_COUNT: '3' # optional
# TIMEOUT: '1800' # optional
# SUB_FOLDER: '/src' # optional
# EXCLUDE_KEYS: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# ALIAS_PATTERNS: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# USAGE_PATTERNS: feature_flags\.enabled\(:CC_KEY\)
# VERBOSE: 'true' # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
#### Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `CONFIG_ID` | ID of the ConfigCat config to scan against. | ☑ | |
| `CONFIGCAT_API_HOST` | ConfigCat Management API host. | | `api.configcat.com` |
| `LINE_COUNT` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `TIMEOUT` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `SUB_FOLDER` | Sub-folder to scan, relative to the repository root folder. | | |
| `EXCLUDE_KEYS` | List of feature flag keys that must be excluded from the scan report. | | |
| `ALIAS_PATTERNS` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `USAGE_PATTERNS` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `VERBOSE` | Turns on detailed logging. | | false |
---
### Bitrise - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [Bitrise Step](https://www.bitrise.io/integrations/steps/configcat-feature-flag-sync) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. [Bitrise](https://www.bitrise.io/) is full-featured mobile CI/CD platform. You can find more information about Bitrise Steps [here](https://devcenter.bitrise.io/en/steps-and-workflows/introduction-to-steps.html).
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following step to the workflows section of your `bitrise.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- configcat-feature-flag-sync@0:
inputs:
- configcat_config_id: 'PASTE-YOUR-CONFIG-ID-HERE' # required
# - line-count: 3 # optional
# - sub-folder: 'src' # optional
# - exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# - alias-patterns: "(\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\)" # optional
# - usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# - verbose: true # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
#### Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `configcat_config_id` | The [config ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id) tells the step which feature flags it should search for in your source code. | ☑ | |
| `configcat_api_host` | ConfigCat Management API host. | | `api.configcat.com` |
| `line_count` | Code snippet line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `sub_folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
### CircleCI Orb - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [CircleCI Orb](https://circleci.com/developer/orbs/orb/configcat/scan-repository) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about CircleCI Orbs [here](https://circleci.com/orbs/).
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in [CircleCI Environment Variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new CircleCI YAML config in your repository under the `.circleci` folder, and put the following snippet into it. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
version: 2.1
orbs:
configcat: configcat/scan-repository@1.11.1
workflows:
main:
jobs:
- configcat/scan:
config-id: PASTE-YOUR-CONFIG-ID-HERE # required
file-url-template: 'https://github.com/your/repo/blob/{commitHash}/{filePath}#L{lineNumber}' # optional
commit-url-template: 'https://github.com/your/repo/commit/{commitHash}' # optional
# line-count: 3 # optional
# timeout: 1800 # optional
# sub-folder: 'src' # optional
# exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# alias-patterns: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# verbose: true # optional
```
4. Commit & push your changes.
The above example configures a workflow that executes the scan and code reference upload on every git `push` event. Scan reports are uploaded for each branch of your repository that triggers the workflow.
#### Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------- |
| `config-id` | ID of the ConfigCat config to scan against. | ☑ | |
| `api-host` | ConfigCat Management API host. | | `api.configcat.com` |
| `api-user` | Name of the environment variable where the [ConfigCat Management API basic authentication username](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_USER |
| `api-pass` | Name of the environment variable where the [ConfigCat Management API basic authentication password](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_PASS |
| `file-url-template` | Template url used to generate VCS file links. Available template parameters: `commitHash`, `filePath`, `lineNumber`. Example: `https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}` | | |
| `commit-url-template` | Template url used to generate VCS commit links. Available template parameters: `commitHash`. Example: `https://github.com/my/repo/commit/{commitHash}` | | |
| `line-count` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `timeout` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `sub-folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
### GitHub Action - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [Scan Repository GitHub Action](https://github.com/marketplace/actions/configcat-scan-repository) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about GitHub Actions [here](https://github.com/features/actions).
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in your repository's [GitHub Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new Actions workflow in your GitHub repository under the `.github/workflows` folder, and put the following snippet into it. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
on: [push]
name: Code references
jobs:
scan-repo:
runs-on: ubuntu-latest
name: Scan repository for code references
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Scan & upload
uses: configcat/scan-repository@v2
with:
api-user: ${{ secrets.CONFIGCAT_API_USER }}
api-pass: ${{ secrets.CONFIGCAT_API_PASS }}
config-id: PASTE-YOUR-CONFIG-ID-HERE
# line-count: 5 # optional
# timeout: 1800 # optional
# sub-folder: src # optional
# exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# alias-patterns: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) #optional
# usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional, comma delimited flag key usage patterns
# verbose: true # optional
```
4. Commit & push your action.
The above example configures a workflow that executes the scan and code references upload on every git `push` event. Scan reports are uploaded for each branch of your repository that triggers the workflow.
#### Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `config-id` | ID of the ConfigCat config to scan against. | ☑ | |
| `api-user` | [ConfigCat Management API basic authentication username](https://app.configcat.com/my-account/public-api-credentials). | ☑ | |
| `api-pass` | [ConfigCat Management API basic authentication password](https://app.configcat.com/my-account/public-api-credentials). | ☑ | |
| `api-host` | ConfigCat Management API host. | | `api.configcat.com` |
| `line-count` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `timeout` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `sub-folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
### GitLab - Scan your source code for feature flags
Copy page
This section describes how to use the [ConfigCat CLI](https://configcat.com/docs/advanced/cli.md) in [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
#### Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in GitLab's [CI/CD Variables](https://docs.gitlab.com/ee/ci/variables/) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new or open your existing `.gitlab-ci.yml` file, and put the following job into it. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
configcat-scan-repository:
stage: deploy # the job will run in the deploy phase, but you can choose from any other phases you have
image:
name: configcat/cli:2.4.2
entrypoint: ['']
script:
- configcat scan $CI_PROJECT_DIR
--config-id=PASTE-YOUR-CONFIG-ID-HERE
--repo=${CI_PROJECT_NAME}
--branch=${CI_COMMIT_REF_NAME}
--file-url-template=https://gitlab.com/${CI_PROJECT_PATH}/blob/{commitHash}/{filePath}#L{lineNumber}
--commit-url-template=https://gitlab.com/${CI_PROJECT_PATH}/commit/{commitHash}
--runner="ConfigCat GitLab Job"
--upload
--non-interactive
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
---
### CLI - Add to CI/CD pipelines manually
Copy page
This section describes how to use the [ConfigCat CLI](https://configcat.com/docs/advanced/cli.md) to scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
#### Prerequisites[](#prerequisites "Direct link to Prerequisites")
* [Install](https://configcat.com/docs/advanced/cli.md#installation) the CLI in your CI/CD or local environment.
* [Setup](https://configcat.com/docs/advanced/cli.md#setup) the CLI with your ConfigCat Management API credentials.
* Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
#### Scan & Upload[](#scan--upload "Direct link to Scan & Upload")
To initiate the scanning with uploading the results, you can use the `scan` command with the `--upload` option.
##### With Git VCS[](#with-git-vcs "Direct link to With Git VCS")
The scan command detects when it's being executed on a Git repository and automatically [extracts additional information](https://configcat.com/docs/advanced/code-references/overview.md#scanning-git-repositories). The following snippet shows a minimal example that uses only the required parameters in the case of a Git repository.
```bash
configcat scan /path/to/your/repo \
--config-id YOUR-CONFIG-ID \ # required
--repo YOUR-REPOSITORY-NAME \ # required
--upload # upload the scan report
```
You can use the optional template URL parameters for generating VCS links to your source code.
```bash
configcat scan /path/to/your/repo \
--config-id YOUR-CONFIG-ID \ # required
--repo YOUR-REPOSITORY-NAME \ # required
--file-url-template "https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}" \ # optional, used to generate VCS file links
--commit-url-template "https://github.com/my/repo/commit/{commitHash}" \ # optional, used to generate VCS commit links
--upload # upload the scan report
```
info
The template parameters (`filePath`, `lineNumber`, and `commitHash`) are automatically replaced by the CLI based on the collected information from the Git repository.
##### With Non-Git VCS[](#with-non-git-vcs "Direct link to With Non-Git VCS")
As the `scan` command cannot determine such information as `branch` and `commitHash` when you execute it on a non-Git repository, you have to set these parameters manually.
```bash
configcat scan /path/to/your/repo \
--config-id YOUR-CONFIG-ID \ # required
--repo YOUR-REPOSITORY-NAME \ # required
--branch BRANCH-NAME \ # required in case of non-git repository
--commit-hash \ # optional, used to show it on the report and generate commit links
--file-url-template "https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}" \ # optional, used to generate VCS file links
--commit-url-template "https://github.com/my/repo/commit/{commitHash}" \ # optional, used to generate VCS commit links
--upload # upload the scan report
```
##### Docker[](#docker "Direct link to Docker")
After [installing](https://configcat.com/docs/advanced/cli.md#installation) the ConfigCat CLI with Docker, you can scan your repository by mounting its folder as a volume and setting the [ConfigCat Management API credentials](https://app.configcat.com/my-account/public-api-credentials) as environment variables on the executing container.
```bash
docker run --rm \
-v /path/to/your/repo:/repository \ # mount the repository as volume
-e CONFIGCAT_API_USER=YOUR-API-USER \ # Management API username
-e CONFIGCAT_API_PASS=YOUR-API-PASS \ # Management API password
configcat/cli scan /repository \ # scan the mounted volume
--config-id YOUR-CONFIG-ID \ # required
--repo YOUR-REPOSITORY-NAME \ # required
--upload # upload the scan report
```
#### Reference[](#reference "Direct link to Reference")
See the `scan` command's [reference documentation](https://configcat.github.io/cli/configcat-scan.html) for all available command parameters.
---
### Scan & Upload Code References Overview
Copy page
ConfigCat's [CLI](https://configcat.com/docs/advanced/cli.md) has the ability to scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
This feature makes the elimination of the technical debt easier, as it can show which repositories reference your feature flags and settings in one centralized place on your [Dashboard](https://app.configcat.com).
You can integrate the CLI into your CI/CD pipeline or use it with other execution mechanisms like scheduled jobs or VCS push triggered workflows.
#### Scan[](#scan "Direct link to Scan")
The following example shows a simple scan execution that prints the scan result to the console. The `scan` command searches for every feature flag and setting key defined within a selected Config.

If you want to see this in action on your project, run the following command in its root folder:
```bash
configcat scan . --print
```
See the `scan` command's [reference documentation](https://configcat.github.io/cli/configcat-scan.html) for all available command parameters.
##### Deleted Flags[](#deleted-flags "Direct link to Deleted Flags")
As part of the scanning operation, the CLI gathers all deleted feature flags and settings from the last 180 days and looks for their usage in your source code. When it finds a reference to a deleted feature flag or setting, it prints a warning that lists their keys.
```bash
[warning]: 5 deleted feature flag/setting reference(s) found in 4 file(s). Keys: [featureThatWasDeleted1, featureThatWasDeleted2]
```
##### Exclude Flags from Scanning[](#exclude-flags-from-scanning "Direct link to Exclude Flags from Scanning")
There's an option to exclude feature flags or settings from the scanning operation by their keys.
```bash
configcat scan --exclude-flag-keys featureFlagToExclude1 featureFlagToExclude2
```
#### Config ID[](#config-id "Direct link to Config ID")
In non-interactive environments, like in a CI/CD pipeline, you have to pass the ID of your ConfigCat Config that you want to scan against. The scanner will use this ID to determine which feature flags & settings to search for in your source code.
To get the ID of a Config, follow the steps below:
1. Go to your [ConfigCat Dashboard](https://app.configcat.com), select the desired Config, and click the code references icon on one of your feature flags.

2. Copy the Config ID from the highlighted box.

#### How Scanning Works[](#how-scanning-works "Direct link to How Scanning Works")
The scanner looks for feature flag and setting keys between quotation marks (`'` `"` `` ` ``) in the first place.
info
There's an option to extend the feature flag and setting key usage regex patterns with the `--usage-patterns` argument of the `scan` command.
```bash
configcat scan --usage-patterns "" ""
```
Usage patterns can also be set via the `CONFIGCAT_USAGE_PATTERNS` environment variable as a comma delimited list.
```bash
export CONFIGCAT_USAGE_PATTERNS=",";
```
The regex pattern must include the `CC_KEY` placeholder that represents the actual feature flag or setting key in your code. For example, the following pattern allows the recognition of Ruby symbols as flag key usages:
```bash
configcat scan --usage-patterns ":CC_KEY"
```
It will match the following usage:
```ruby
if FeatureFlags.enabled(:my_feature_key)
#...
end
```
##### Aliases[](#aliases "Direct link to Aliases")
The found keys' context is examined for **aliases**, like variables, constants, or enumerations used to store these keys. **Aliases** are treated as indirect references and are included in the searching process.
For example, the following `C#` constant's name (`MyAwesomeFeature`) will be recognized as an alias:
```csharp
public static class FeatureFlagKeys
{
public const string MyAwesomeFeature = "my_awesome_feature";
}
```
The scanner will treat this constant's usage as an indirect reference to the flag.
```csharp
if (await configCatClient.GetValueAsync(FeatureFlagKeys.MyAwesomeFeature, false))
{
// the feature is on.
}
```
info
The alias recognition **adapts to the characteristics of different languages**. For example, it can find aliases in `Go` constants/variable assignments:
```go
const (
myAwesomeFeature string = "my_awesome_feature"
)
myAwesomeFeature := "my_awesome_feature"
```
And in `Swift` enums/variable assignments as well:
```swift
enum FlagKeys : String {
case MyAwesomeFeature = "my_awesome_feature"
}
let myAwesomeFeature: String = "my_awesome_feature"
```
You can check [here](https://raw.githubusercontent.com/configcat/cli/main/test/ConfigCat.Cli.Tests/alias.txt) a bunch of other samples that we tested.
info
An alias must be at least **30% identical to the feature flag/setting key**. The similarity check is case insensitive and ignores `_` characters. This behavior prevents false recognitions in expressions like `` where `value` shouldn't be treated as alias.
##### Custom alias match patterns[](#custom-alias-match-patterns "Direct link to Custom alias match patterns")
There's an option to set custom regex patterns for identifying additional aliases. The `scan` command accepts a list of patterns via the `--alias-patterns` argument.
```bash
configcat scan --alias-patterns "" ""
```
The CLI also accepts patterns from the `CONFIGCAT_ALIAS_PATTERNS` environment variable as a comma delimited list.
```bash
export CONFIGCAT_ALIAS_PATTERNS=",";
```
###### Match pattern format[](#match-pattern-format "Direct link to Match pattern format")
The regex pattern must include at least one capture group that represents the actual alias. When more than one group is defined, the first one is selected. To bind the actual flag keys to aliases, the CLI uses a `CC_KEY` placeholder to inject the known keys into the pattern.
For example, the following pattern allows to find aliases that point to Ruby symbols:
```bash
configcat scan --alias-patterns "(\w+) = client\.get_value\(:CC_KEY"
```
It will match to the following usage:
```ruby
# 'my_feature_enabled' is now treated as an alias to the 'my_feature_key' flag.
my_feature_enabled = client.get_value(:my_feature_key, false)
```
note
The CLI implicitly adds the optional `` ` ``, `'`, `"` wrapping around flag keys, so you don't have to wrap the `CC_KEY` placeholder manually.
For example, the pattern `(\w+) = CC_KEY` will either match to `alias = flag_key`, `alias = "flag_key"`, `alias = 'flag_key'`, or ``alias = `flag_key` ``.
##### Wrappers[](#wrappers "Direct link to Wrappers")
In addition to aliases, the scanner also looks for different feature flag/setting key usage patterns. This helps to recognize functions and properties used to wrap direct ConfigCat SDK calls as indirect references. Aliases are also included in this search.
For example, the scanner will treat the `IsMyAwesomeFeatureEnabled` function of the following `C#` wrapper class as an indirect reference:
```csharp
public class FeatureFlagProvider
{
public async Task IsMyAwesomeFeatureEnabled(bool defaultValue = false)
{
return await configCatClient.GetValueAsync("my_awesome_feature", defaultValue);
}
}
```
And will include its usage in the scan report:
```csharp
if (await featureFlagProvider.IsMyAwesomeFeatureEnabled())
{
// the feature is on.
}
```
info
The scanner uses the following patterns to look for wrapper usages (case insensitive):
* `[.|->|::]{settingKeyOrAlias}`
* `[.|->|::]get{settingKeyOrAlias}`
* `[.|->|::]is{settingKeyOrAlias}`
* `[.|->|::]is{settingKeyOrAlias}enabled`
Given the key/alias `my_awesome_feature`, the scanner will find any of the following usage examples:
* `.my_awesome_feature` (also: `->my_awesome_feature` / `::my_awesome_feature`)
* `.MY_AWESOME_FEATURE` (also: `->MY_AWESOME_FEATURE` / `::MY_AWESOME_FEATURE`)
* `.get_my_awesome_feature` (also: `->get_my_awesome_feature` / `::get_my_awesome_feature`)
* `.GET_MY_AWESOME_FEATURE` (also: `->GET_MY_AWESOME_FEATURE` / `::GET_MY_AWESOME_FEATURE`)
* `.is_my_awesome_feature` (also: `->is_my_awesome_feature` / `::is_my_awesome_feature`)
* `.is_my_awesome_feature_enabled` (also: `->is_my_awesome_feature_enabled` / `::is_my_awesome_feature_enabled`)
* `.myAwesomeFeature` (also: `->myAwesomeFeature` / `::myAwesomeFeature`)
* `.getMyAwesomeFeature` (also: `->getMyAwesomeFeature` / `::getMyAwesomeFeature`)
* `.isMyAwesomeFeature` (also: `->isMyAwesomeFeature` / `::isMyAwesomeFeature`)
* `.isMyAwesomeFeatureEnabled` (also: `->isMyAwesomeFeatureEnabled` / `::isMyAwesomeFeatureEnabled`)
* `.IsMyAwesomeFeatureEnabled` (also: `->IsMyAwesomeFeatureEnabled` / `::IsMyAwesomeFeatureEnabled`)
#### Upload Scan Reports[](#upload-scan-reports "Direct link to Upload Scan Reports")
You have the option to upload scan reports for each branch of your repository to ConfigCat. Each scan report is associated to one of these branches.
The following screenshot shows how an uploaded report looks like.

##### Scanning Git Repositories[](#scanning-git-repositories "Direct link to Scanning Git Repositories")
The `scan` command automatically detects when it's being executed on a git repository. It collects additional information from Git like the current **branch name**, the actual **commit hash**, and each active **remote branch**. These extra details are used to enrich the uploaded report on the ConfigCat Dashboard with links to your actual source code.
info
If you are not using Git as VCS, you have to set at least the `--branch` parameter of the `scan` command.
##### Template URLs[](#template-urls "Direct link to Template URLs")
The `scan` command's `--file-url-template` and `--commit-url-template` parameters are used for generating links to your repository. Based on the information available during the scanning, the CLI replaces the corresponding template parameters to generate the actual links.
* **File URL template**: Used to generate VCS file links. Available template parameters:
* `commitHash`
* `filePath`
* `lineNumber`
With the following example template URL: `https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}` For the file `src/example.js`, the result is: `https://github.com/my/repo/blob/4451d61b63a4b4499ed5c607be6c40ce9eeadb9c/src/example.js#L69`
* **Commit URL template**: Used to generate VCS commit links. Available template parameters:
* `commitHash`
With the following example template URL: `https://github.com/my/repo/commit/{commitHash}` For the commit hash `4451d61b63a4b4499ed5c607be6c40ce9eeadb9c`, the result is: `https://github.com/my/repo/commit/4451d61b63a4b4499ed5c607be6c40ce9eeadb9c`
info
When these template URLs are not set, the uploaded report will not contain VCS links.
##### Stale Branches[](#stale-branches "Direct link to Stale Branches")
When the scan is executed on a Git repository, the CLI attaches the currently active remote branches to the uploaded report. This information is used for cleaning up each stale report that belongs to a deleted branch.
##### CI/CD Integrations[](#cicd-integrations "Direct link to CI/CD Integrations")
We prepared the following integrations to simplify the usage of the scanner in your CI/CD workflow:
* [GitHub Action](https://configcat.com/docs/advanced/code-references/github-action.md)
* [CircleCI Orb](https://configcat.com/docs/advanced/code-references/circleci-orb.md)
* [GitLab CI/CD](https://configcat.com/docs/advanced/code-references/gitlab-ci.md)
* [Azure DevOps](https://configcat.com/docs/advanced/code-references/azure-devops.md)
* [Bitbucket Pipe](https://configcat.com/docs/advanced/code-references/bitbucket-pipe.md)
* [Bitrise Step](https://configcat.com/docs/advanced/code-references/bitrise-step.md)
##### Manual Integration[](#manual-integration "Direct link to Manual Integration")
If your workflow doesn't have an integration, you can follow the instructions [here](https://configcat.com/docs/advanced/code-references/manual.md) to set scan executions directly with the ConfigCat CLI.
#### Ignore Files[](#ignore-files "Direct link to Ignore Files")
The `scan` command respects all include and exclude patterns listed inside `.gitignore` and `.ignore` files within the scanned directory. In addition, you can create an extra `.ccignore` file with patterns that the scanner must take into account.
Each pattern must follow the [gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format).
---
### Config V2 Overview
Copy page
Config V2 is a new version of ConfigCat. It comes with a new Dashboard, Public Management API, SDKs, and features.
#### What's new?[](#whats-new "Direct link to What's new?")
* A bunch of new features and improvements listed below.
* New config editor UI on the Dashboard.
* [New and improved config JSON schema.](https://github.com/configcat/config-json)
* New API: [See the API Docs.](https://configcat.com/docs/api/reference/configcat-public-management-api.md)
* New SDKs: [See the supported SDK versions.](https://configcat.com/docs/advanced/config-v2-sdk-compatibility.md)
#### How to migrate from Config V1 to Config V2?[](#how-to-migrate-from-config-v1-to-config-v2 "Direct link to How to migrate from Config V1 to Config V2?")
See the [Config V2 Migration Guide](https://configcat.com/docs/advanced/config-v2-migration-guide.md). If you get stuck or have any questions about the migration, feel free to [contact us](https://configcat.com/support/).
#### New features[](#new-features "Direct link to New features")
##### AND conditions[](#and-conditions "Direct link to AND conditions")
With AND conditions, you can define more complex Targeting Rules, such as "serve this value for the users who use my Android app AND whose email domain is '@example.com'".
You can add multiple conditions to a Targeting Rule and they will be evaluated with an AND connection between them.

##### New comparators[](#new-comparators "Direct link to New comparators")
With the new comparators, you can create Targeting Rules based on date comparisons, array comparisons, and more.
* New text and confidential text comparators: `EQUALS`, `NOT EQUALS`, `STARTS WITH ANY OF`, `ENDS WITH ANY OF`, `NOT STARTS WITH ANY OF`, `NOT ENDS WITH ANY OF`.
* New array comparators: `ARRAY CONTAINS ANY OF`, `ARRAY NOT CONTAINS ANY OF`.
* New date comparators: `BEFORE`, `AFTER`.

##### Prerequisite flags[](#prerequisite-flags "Direct link to Prerequisite flags")
With prerequisite flags, you can create feature flags that depend on other feature flags. Prerequisite feature flags (aka. master feature flag, inter-dependent feature flag, global toggle) are particularly useful for managing complex feature dependencies and ensuring a smooth user experience during feature rollouts.

##### Comparison value hints[](#comparison-value-hints "Direct link to Comparison value hints")
With comparison value hints, you can associate arbitrary text with your comparison values. This way you can add a description to your comparison value list items that helps you remember what they are for.
##### Percentage Options within Targeting Rules[](#percentage-options-within-targeting-rules "Direct link to Percentage Options within Targeting Rules")
You can add Percentage Options to your Targeting Rules. This is useful if you want to create more complex Targeting Rules, such as "turn on the feature for 20% of the users who are on iOS, and off for 80%".

##### Custom Percentage Attributes[](#custom-percentage-attributes "Direct link to Custom Percentage Attributes")
With custom Percentage Attributes, you can create Percentage Options based on custom attributes. This way you can create Percentage Options based on any of your user attributes. For example, you can create a Percentage Option that is based on the user's company or organization. So you can serve a value for 20% of the users from company A and serve another value for 80% of the users from company B.

---
### Config V2 Migration Guide
Copy page
This guide will help you migrate from Config V1 to Config V2.
#### What is Config V2?[](#what-is-config-v2 "Direct link to What is Config V2?")
**Config V2 is the next generation of ConfigCat.** It comes with a new Dashboard, Public Management API and SDKs.
**Config V2 supports all the features of V1**, so you can continue using those, but **it offers interesting new features as well**. However, you won't be able to use the new features with the V1 versions of the Dashboard, Public Management API and SDKs.
Read more about the new features in the [Config V2 Overview](https://configcat.com/docs/advanced/config-v2.md).
#### A few things to consider before migration[](#a-few-things-to-consider-before-migration "Direct link to A few things to consider before migration")
* **Migration from Config V1 means that a V2 config will be copied from the V1 config. The V1 config will remain unchanged and accessible.** The V2 version will have a new SDK key for each environment.
* **Config V2 and V1 are completely separate.** They don't affect each other in any way. You can use them side by side.
* **There is no automatic sync between the V1 and V2 configs.** If you want to keep them in sync, you have to manually update the V2 config when you make changes to the V1 config and vice versa.
* There is no pressure to migrate. Although we have plans to phase out V1 eventually, you can stay on it for a long time.
* Once the migration process is started, it's recommended to migrate your V1 configs to V2 as quickly as possible to avoid confusion.
* Keep in mind that the [integrations](https://app.configcat.com/integrations) and [webhooks](https://app.configcat.com/product/webhooks) connected to V1 configs are not migrated automatically and you have to set them up manually for the migrated V2 configs.
* Every newly created config will be a V2 config by default.
#### Migrating from Config V1 to Config V2[](#migrating-from-config-v1-to-config-v2 "Direct link to Migrating from Config V1 to Config V2")
The migration process starts with copying your V1 config to a new V2 one and updating your applications to use the new config. The complete process is the following:
##### Step 1: Create the V2 config[](#step-1-create-the-v2-config "Direct link to Step 1: Create the V2 config")
1. Open the ConfigCat Dashboard and click on the `Start migration` button on top of a V1 config.
2. Click `Create V2 config` to create a new config with the same settings as the V1 config.
It's important to note that the V2 config will be created with the same settings as the V1 config and the V1 config will still be accessible and unchanged.
##### Step 2: Upgrade the ConfigCat SDK version[](#step-2-upgrade-the-configcat-sdk-version "Direct link to Step 2: Upgrade the ConfigCat SDK version")
In your application, upgrade the ConfigCat SDK to the latest version. Old versions of the SDK will not be able to access the new config. Make sure you upgrade every application that uses the migrated V2 config.
Here is a list of the SDKs that support Config V2: [See the supported SDK versions.](https://configcat.com/docs/advanced/config-v2-sdk-compatibility.md)
##### Step 3: Update the ConfigCat SDK Key[](#step-3-update-the-configcat-sdk-key "Direct link to Step 3: Update the ConfigCat SDK Key")
In your application, replace the old ConfigCat SDK Key with the new one (i.e. with the one that belongs to the V2 version of the config) in every environment. The new key can be found on the ConfigCat Dashboard on the V2 config's page.
##### Step 4: Deploy your application[](#step-4-deploy-your-application "Direct link to Step 4: Deploy your application")
Deploy your application to production and wait until all your users upgrade to the new version. You can check the migration status on the ConfigCat Dashboard under the migration status page that is available from a config's context menu in the sidebar.
##### Step 5: Clean up[](#step-5-clean-up "Direct link to Step 5: Clean up")
After confirming that all your users have transitioned to the latest version of your application, you can finalize the migration by removing the V1 config.
To verify that the V1 configs haven't been accessed for a significant period, check the migration status page accessible via a config's context menu in the sidebar. This step helps eliminate any mix-ups and prevents the unintended use of outdated configurations.
caution
Once you delete the V1 config, you won't be able to restore it.
---
### Config V2 SDK Compatibility
Copy page
This table shows which SDK versions support Config V2. Read more about [Config V2](https://configcat.com/docs/advanced/config-v2.md)
| SDK | Version | Release Notes |
| ------------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------- |
| .NET | >= v9.1.0 | |
| Android (Java) | >= v10.1.0 | |
| C++ | >= v4.0.0 | |
| Dart (Flutter) | >= v4.1.0 | |
| Elixir | >= v4.0.0 | |
| Go | >= v9.0.3 | |
| Java | >= v9.1.0 | |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node.js) | >= v1.0.0 | |
| JavaScript - Legacy | >= v9.5.0 | |
| JavaScript (Chromium Extension) - Legacy | >= v2.4.0 | |
| JavaScript (SSR) - Legacy | >= v8.4.0 | |
| Kotlin Multiplatform | >= v3.0.0 | |
| Node.js - Legacy | >= v11.3.0 | |
| PHP 8.1+ | >= v9.1.0 | |
| PHP 7.1+ | >= v3.0.0 | |
| Python | >= v9.0.3 | |
| React | >= v4.6.0 | |
| Ruby | >= v8.0.0 | |
| Rust | >= v0.1.0 | |
| Swift (iOS) | >= v11.0.0 | |
| Unreal Engine | >= v2.0.0 | |
---
### Data Governance - CDN
Copy page
ConfigCat's Data Governance feature gives you control over how and where your config JSONs are published and served from. This helps you comply with regional data handling requirements such as GDPR.
#### CDN - Data Centers[](#cdn---data-centers "Direct link to CDN - Data Centers")
To ensure high availability and low response times worldwide, ConfigCat provides multiple global data centers, each with multiple CDN nodes for built-in redundancy and failover.
##### ConfigCat Data Center locations[](#configcat-data-center-locations "Direct link to ConfigCat Data Center locations")
ConfigCat uses Cloudflare Edge Cache Network to deliver the configuration JSONs to the SDKs. Read more about Cloudflare data centers [here](https://www.cloudflare.com/network/).
#### How to govern the data?[](#how-to-govern-the-data "Direct link to How to govern the data?")
Currently available geographical areas:
##### Global \[Default][](#global-default "Direct link to Global [Default]")
Provides geo-location based load balancing on all nodes around the globe to ensure the lowest response times.
##### EU Only[](#eu-only "Direct link to EU Only")
Compliant with GDPR. This way your data will never leave the EU.
#### Set preferences on the Dashboard[](#set-preferences-on-the-dashboard "Direct link to Set preferences on the Dashboard")
Open [Data Governance page](https://app.configcat.com/organization/data-governance) and follow the steps to set preferences.
> Only team members with Organization Admin role can access Data Governance preferences.
#### Set up the ConfigCat SDK in your application code[](#set-up-the-configcat-sdk-in-your-application-code "Direct link to Set up the ConfigCat SDK in your application code")
Make sure the `dataGovernance` option is specified when initializing the ConfigCat SDK in your application code.
> The `dataGovernance` option's value must be in sync with the selected option on the Dashboard.
#### Troubleshooting[](#troubleshooting "Direct link to Troubleshooting")
###### What if I forget to specify the `dataGovernance` option?[](#what-if-i-forget-to-specify-the-datagovernance-option "Direct link to what-if-i-forget-to-specify-the-datagovernance-option")
By default, the ConfigCat SDK contacts the ConfigCat Global CDN. However, if you switch to the EU CDN on the Dashboard, your config JSONs will only be published to the EU CDN nodes. Therefore, if you forget to specify the `dataGovernance` option when initializing the ConfigCat SDK, feature flag data download requests will need to be redirected to the EU CDN. To avoid this, it's recommended to specify the correct `dataGovernance` option, otherwise response times can be significantly longer.
###### `Warning: The dataGovernance parameter specified at the client initialization is not in sync with the preferences on the ConfigCat Dashboard....`[](#warning-the-datagovernance-parameter-specified-at-the-client-initialization-is-not-in-sync-with-the-preferences-on-the-configcat-dashboard "Direct link to warning-the-datagovernance-parameter-specified-at-the-client-initialization-is-not-in-sync-with-the-preferences-on-the-configcat-dashboard")
**Don't worry,** your feature flags will still be served. See above example.
---
### MCP Server
Copy page
#### Overview[](#overview "Direct link to Overview")
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) is an open protocol that standardizes how applications provide context to large language models (LLMs). The ConfigCat MCP server lets you manage feature flags and configurations via the Public Management API seamlessly from AI tools. It also enables your code editor to understand your feature flags, integrate the appropriate ConfigCat SDK into your project or even create new feature flags directly in your codebase.
Your browser does not support the video tag. You can download the video here: [mcp-demo.mp4](https://configcat.com/docs/assets/mcp/mcp-demo.mp4).
#### Features[](#features "Direct link to Features")
* Manage organizations, members and permissions
* Create and update products, configs, and environments
* Manage feature flags and settings
* Manage tags and user segments
* Connect with integrations and webhooks
* Track activity with audit logs and zombie flag (stale flag) reports
* Find code references linked to your features
* Integrate ConfigCat SDK and implement feature flags in your project
#### Prerequisites[](#prerequisites "Direct link to Prerequisites")
* [Node.js](https://nodejs.org) version 16 or higher installed
* [Public Management API basic auth credentials](https://app.configcat.com/my-account/public-api-credentials) for ConfigCat MCP server created
#### Setup[](#setup "Direct link to Setup")
Supply your [Public Management API basic auth credentials](https://app.configcat.com/my-account/public-api-credentials).
The MCP server's configuration includes the following environment variables:
| Variable | Required | Default | Description |
| -------------------- | -------- | --------------------------- | ----------------------------------- |
| `CONFIGCAT_API_USER` | ☑ | – | Management API basic auth username. |
| `CONFIGCAT_API_PASS` | ☑ | – | Management API basic auth password. |
| `CONFIGCAT_BASE_URL` | | `https://api.configcat.com` | Override API host (rarely needed). |
##### Client Configuration[](#client-configuration "Direct link to Client Configuration")
* Cursor
* Visual Studio Code
* Claude Desktop
1. Install [Cursor](https://cursor.com/)
2. Open **Preferences** → **Cursor Settings** → **MCP & Integrations**
3. Click **Add Custom MCP**
4. Add (or merge) the snippet below into your JSON settings:
```json
{
"mcpServers": {
"ConfigCat": {
"command": "npx",
"args": ["-y", "@configcat/mcp-server"],
"env": {
"CONFIGCAT_API_USER": "YOUR_API_USER",
"CONFIGCAT_API_PASS": "YOUR_API_PASSWORD"
}
}
}
}
```
5. **Save** – the server will start on demand.
6. You can start writing prompts into Cursor's AI panel.
1) Install [VS Code](https://code.visualstudio.com/) and [GitHub Copilot](https://code.visualstudio.com/docs/copilot/setup)
2) Create a `.vscode/mcp.json` file in your project root with the following content:
```json
{
"servers": {
"ConfigCat": {
"command": "npx",
"args": ["-y", "@configcat/mcp-server"],
"env": {
"CONFIGCAT_API_USER": "YOUR_API_USER",
"CONFIGCAT_API_PASS": "YOUR_API_PASSWORD"
}
}
}
}
```
3. Save the settings file. The MCP server should now be available in VS Code.
4. You can start writing prompts into VS Code's AI panel.
1) Install [Claude Desktop](https://claude.ai/download)
2) Open **Settings** → **Developer**
3) Click **Edit Config**
4) In `claude_desktop_config.json` add:
```json
{
"mcpServers": {
"ConfigCat": {
"command": "npx",
"args": ["-y", "@configcat/mcp-server"],
"env": {
"CONFIGCAT_API_USER": "YOUR_API_USER",
"CONFIGCAT_API_PASS": "YOUR_API_PASSWORD"
}
}
}
}
```
5. **Save** & restart Claude Desktop.
info
Replace `YOUR_API_USER` and `YOUR_API_PASSWORD` environment variables with your [Public Management API basic auth credentials](https://app.configcat.com/my-account/public-api-credentials).
#### Interaction[](#interaction "Direct link to Interaction")
After you install the ConfigCat MCP server in your AI client, you can prompt your agent to create or manage your feature flags and configurations. Typically you need to click Run tool (or the equivalent option in your AI client) to execute the result.
For example, you could try asking
> Create a boolean feature flag called "my\_awesome\_feature" in the "Backend" config
or
> Turn the "my\_awesome\_feature" flag ON in all environments
or
> Update the "my\_awesome\_feature” flag in dev environment so it’s only enabled for users in Canada
or
> Create a new feature flag by cloning the configuration of the "my\_awesome\_feature" flag, and name it "my\_another\_awesome\_feature".
or
> Update the "my\_awesome\_feature" flag description: "When enabled, show my awesome feature.”
or
> List the stale feature flags that haven’t been modified in the past 6 days.
or
> Show who last modified the "myNewAwesomeFeature" flag, and to what.
or
> Invite sarah@example.com to the "Main" product with "Administrators" permissions.
#### See Also[](#see-also "Direct link to See Also")
* [ConfigCat MCP server GitHub repository](https://github.com/configcat/mcp-server)
* [ConfigCat MCP server available tools](https://github.com/configcat/mcp-server?tab=readme-ov-file#available-tools)
* [Management API Reference](https://configcat.com/docs/api/reference/configcat-public-management-api.md)
* [How to Manage Feature Flags with ConfigCat's MCP Server - Blog post](https://configcat.com/blog/mcp-server-feature-flags/)
* [How to Migrate from Statsig to ConfigCat: Feature Flag Migration Using MCP Servers - Blog post](https://configcat.com/blog/migrate-from-statsig/)
---
### Migration from LaunchDarkly
Copy page
This document is for current LaunchDarkly users who want to migrate to ConfigCat. It guides you through the migration process while providing information on the technical differences between the two services that you need to be aware of.
Migration can be done on a LaunchDarkly project basis, and migration of a project usually consists of the following three steps:
1. Migrating LaunchDarkly feature flags and segments to ConfigCat
2. Adjusting the code of your applications to use ConfigCat instead of LaunchDarkly
3. Migrating LaunchDarkly teams and permissions to ConfigCat
ConfigCat provides a wizard-like tool that is able to do the heavy lifting for step 1. However, there is currently no automation for step 2 and 3. So please expect these steps to require some manual work.
However, before diving into it all, please check [this list](https://configcat.com/docs/sdk-reference/overview.md) to see if ConfigCat supports the platform your applications are running on. If not, feel free to [contact us](https://configcat.com/support). Maybe we can still figure out a way for you to migrate to ConfigCat.
#### Getting started[](#getting-started "Direct link to Getting started")
To be able to perform the migration, it's essential that you have a basic understanding of ConfigCat's main concepts and hierarchy. So, as the very first step, please read through [this brief guide](https://configcat.com/docs/main-concepts.md).
LaunchDarkly projects correspond to ConfigCat products in the ConfigCat hierarchy. However, as you already know, products are not standalone entities, they are contained by a ConfigCat organization.
So, to get started with migration, you will need to have a ConfigCat account and be a member of the ConfigCat organization that you want to host the products corresponding to the projects you plan to migrate from LaunchDarkly. You will also need to have the Organization Admin permission in that ConfigCat organization to be able to create products.
* If the target ConfigCat organization does not exist yet, you can create one by [signing up](https://app.configcat.com/auth/signup). During the signup process, you will have the opportunity to create your own organization, in which you will have the Organization Admin permission by default.
* Otherwise, you will need to get an invitation to the target ConfigCat organization, and after joining, you will need to request the Organization Admin permission.
Once the target ConfigCat organization is set up and you have the necessary permissions in it, you can start the actual migration.
#### Migrate LaunchDarkly feature flags and segments to ConfigCat[](#migrate-launchdarkly-feature-flags-and-segments-to-configcat "Direct link to Migrate LaunchDarkly feature flags and segments to ConfigCat")
It is recommended to migrate your LaunchDarkly feature flags and segments to ConfigCat first, using ConfigCat's official import tool, which was designed for this specific purpose.
The tool also takes care of creating the corresponding ConfigCat products and environments, and it does everything possible to reproduce your LaunchDarkly feature flags and segments in ConfigCat so they match the original evaluation behavior as closely as possible.
##### Using the import tool[](#using-the-import-tool "Direct link to Using the import tool")
To launch the import tool, open the dropdown menu in the top left corner of the [ConfigCat Dashboard](https://app.configcat.com/organization), navigate to the Organization Overview page, then click the card labeled "Import from LaunchDarkly".

This will take you to a page with a wizard-like UI:

Follow the instructions and go through the steps to perform the import.
Feel free to experiment with the import tool. You can't really cause any irreversible damage by doing so. After finishing an import, you can delete the imported products in ConfigCat and start over if you are not satisfied with the result.
It is also possible to re-import products or specific parts of those without having to delete the products created previously. The import tool is able to update the existing entities with fresh data. However, this may involve undoable overwriting of existing data, so please be careful. The import tool will warn you if something like this is about to happen.
##### Targeting toggle translation mode[](#targeting-toggle-translation-mode "Direct link to Targeting toggle translation mode")
In step 3 of the wizard, you may need to make a decision that might not be self-evident.
LaunchDarkly feature flags have a [toggle](https://docs.launchdarkly.com/home/flags/toggle) that allows you to enable or disable targeting for the specific feature flag. However, there is no similar feature in ConfigCat.
So, in case the LaunchDarkly projects you selected for import contain feature flags where the targeting toggle is turned off in some of the environments, you need to decide how to work around such cases.
Your options are the following:
###### Ignore targeting toggle and import rules anyway[](#ignore-targeting-toggle-and-import-rules-anyway "Direct link to Ignore targeting toggle and import rules anyway")
This will result in an evaluation behavior different from LaunchDarkly. Choose this option if you want to keep your targeting rules even if the targeting toggle is off.
Please consider the following consequences:
* The state of targeting toggles will be ignored.
* The *off variation* values won't be served.
* The targeting rules will be imported and evaluated as if the targeting toggle was on.
###### Respect targeting toggle and don't import rules[](#respect-targeting-toggle-and-dont-import-rules "Direct link to Respect targeting toggle and don't import rules")
This will result in the same evaluation behavior as in LaunchDarkly. Choose this option if you want your feature flags to produce the same values as in LaunchDarkly.
Please consider the following consequences:
* The state of targeting toggles will be respected.
* The *off variation* values will be served.
* The targeting rules won't be imported in environments where the targeting toggle is off.
###### Emulate targeting toggle using a prerequisite flag[](#emulate-targeting-toggle-using-a-prerequisite-flag "Direct link to Emulate targeting toggle using a prerequisite flag")
This is a workaround that combines the upsides of the other two options at the expense of creating extra feature flags. Choose this option if you want to import your targeting rules in all cases, and also want your feature flags to produce the same values as they do in LaunchDarkly.
Please consider the following consequences:
* The state of targeting toggles will be respected, however, for each problematic LaunchDarkly feature flag an extra [prerequisite flag](https://configcat.com/docs/targeting/targeting-rule/flag-condition.md) will be created in ConfigCat to emulate the targeting toggle.
* The *off variation* values will be served.
* The targeting rules will be imported and evaluated depending on the state of the extra prerequisite flag.
##### About the import operation[](#about-the-import-operation "Direct link to About the import operation")
After making your choices on what and how to import in the first steps of the wizard, the import tool performs the operation by importing the selected LaunchDarkly projects one by one. Importing a project consists of two phases:
###### Translation phase[](#translation-phase "Direct link to Translation phase")
First, the import tool translates the LaunchDarkly project to a ConfigCat product. For more details on how this is done, please refer to [this document](https://configcat.com/docs/advanced/migration-from-launchdarkly-translation.md).
It's important to note that the import tool performs translation on a best effort basis. It aims to do translation in such a way that you get a feature flag evaluation behavior as close to the original as possible. However, since there are technical differences between LaunchDarkly and ConfigCat, an accurate translation is not possible in every case.
Such problematic cases are called *translation issues*. The import tool detects and collects these issues during translation, and includes them in the report generated at the end of the import operation so you can review them, and make the necessary adjustments where necessary.
You can find the list of possible translation issues [here](https://configcat.com/docs/advanced/migration-from-launchdarkly-translation.md#translation-issues).
###### Import phase[](#import-phase "Direct link to Import phase")
After the translation phase, the import tool loads the result into ConfigCat. This is when the corresponding ConfigCat product is actually created (or updated if it already exists).
As the import tool has previously performed all the necessary validation and adjustments, generally you shouldn't encounter any issues during this phase. However, in rare cases failures may occur (most likely, due to a concurrent modification in ConfigCat).
The import tool notifies you of such cases, and it also includes the failure details in the report.
##### Final steps[](#final-steps "Direct link to Final steps")
After finishing the import operation, the import tool displays a summary. This shows you the overall success of each LaunchDarkly project selected for import.
* If you see success icons next to every project, it means everything went fine, no significant issues were detected.
* If you see a warning or error icon next to any project, it means that there are significant issues you need to pay closer attention to, and you will almost certainly need to make manual adjustments, or, in case of failure, even repeat the import.
In either case, it's highly recommended to download and go through the report. It provides details about the detected issues, and also includes links to the original and imported entities, which can make it easier for you to look into and resolve the issues.
#### Adjust the code of your applications[](#adjust-the-code-of-your-applications "Direct link to Adjust the code of your applications")
The next step in the migration process is to adjust the code of your applications to use ConfigCat instead of LaunchDarkly to evaluate your feature flags.
This will also require more or less manual work, depending on what API your applications currently use for feature flag evaluation.
##### Adjust a codebase that uses LaunchDarkly SDK[](#adjust-a-codebase-that-uses-launchdarkly-sdk "Direct link to Adjust a codebase that uses LaunchDarkly SDK")
If your applications implement feature flagging by directly consuming the LaunchDarkly SDK API, you will need to change those parts to use the ConfigCat SDK API. We show how to do this through a simple example.
Let's assume you have the following simple Node.js application:
```js
import LaunchDarkly from "@launchdarkly/node-server-sdk";
const sdkKey = process.env.LAUNCHDARKLY_SDK_KEY ?? "#YOUR-SDK-KEY#";
const client = LaunchDarkly.init(sdkKey);
try {
await client.waitForInitialization({ timeout: 10 });
} catch (error) {
console.error(`SDK failed to initialize: ${error}`);
process.exit(1);
}
const context = {
"kind": "multi",
"user": {
"key": "#UNIQUE-USER-IDENTIFIER#",
"name": "Alice",
"email": "alice@example.com",
"country": "UK"
},
"organization": {
"key": "#UNIQUE-ORG-IDENTIFIER#",
"address": {
"city": "London"
}
}
};
const flagValue = await client.variation("isAwesomeFeatureEnabled", context, false);
if (flagValue) {
console.log("Feature is enabled.")
} else {
console.log("Feature is disabled.")
}
process.exit(0);
```
Let's see now step by step how to convert this code to ConfigCat:
1. Uninstall the LaunchDarkly SDK package, and install the ConfigCat one instead:
```bash
npm uninstall @launchdarkly/node-server-sdk
npm install configcat-node
```
2. Instead of the `LaunchDarkly` namespace, import `configcat`:
```js
import configcat from "configcat-node";
```
3. Replace the LaunchDarkly SDK key with the ConfigCat one.
You can obtain it from the [ConfigCat Dashboard](https://app.configcat.com/organization), by selecting the config containing the imported feature flag on the sidebar, and clicking the "VIEW SDK KEY" button in the top right corner of the page.
4. Instead of a LaunchDarkly client instance, obtain a ConfigCat one:
```js
const client = configcat.getClient(sdkKey, configcat.PollingMode.AutoPoll, {
maxInitWaitTimeSeconds: 10
});
```
Please note that the ConfigCat client doesn't maintain a persistent connection to the remote server, but uses different polling strategies to get the data necessary for feature flag evaluation. Refer to the [SDK reference](https://configcat.com/docs/sdk-reference/js/overview.md#creating-the-configcat-client) to learn more about the options. For frontend applications and long-running backend services, Auto Polling mode is usually a good choice.
5. Adjust the wait-for-initialization logic.
* When using Auto Polling mode, you can rewrite it like this:
```js
const clientCacheState = await client.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
/* ... */
process.exit(1);
}
```
Please note that the `waitForReady` method is not available on all platforms. On such platforms, you can't really implement this logic at the moment. However, you don't really need to as the feature flag evaluation methods wait for initialization internally anyway. (It's worth noting that if initialization can't complete within the timeout duration specified by the `maxInitWaitTimeSeconds` option, then feature flag evaluation methods will return the default value you pass to them.)
Actually, you only need this wait-for-initialization logic at the startup of your applications if you want to use [synchronous feature flag evaluation via snapshots](https://configcat.com/docs/sdk-reference/js/overview.md#snapshots-and-synchronous-feature-flag-evaluation).
* For other polling modes, the wait-for-initialization logic doesn't make sense, so just omit it.
6. Rewrite LaunchDarkly contexts to ConfigCat User Objects.
ConfigCat uses the concept of [User Object](https://configcat.com/docs/targeting/user-object.md) to pass user and/or session-related contextual data to feature flag evaluation. It serves the same purpose as [LaunchDarkly contexts](https://launchdarkly.com/docs/home/observability/contexts), but it's a simpler data structure.
To be able to convert a context data structure to a User Object one, you will need to do the following:
* Read [the section on User Objects](https://configcat.com/docs/sdk-reference/js/overview.md#user-object) in the reference of the SDK for your platform.
* Read [this section](https://configcat.com/docs/advanced/migration-from-launchdarkly-translation.md#mapping-between-launchdarkly-contexts-and-configcat-user-objects) to learn how context paths are mapped to User Object attribute names.
For an example of such conversion, see the adjusted code at the end of this section.
Please also keep in mind:
* Some LaunchDarkly SDKs may [automatically provide additional attributes](https://launchdarkly.com/docs/sdk/features/environment-attributes) in contexts. ConfigCat SDKs don't offer a feature like that at the moment, so in case you target such additional attributes in your feature flags, you will need to provide them manually in your applications.
* LaunchDarkly allows multiple attribute values (an array of values) for all clause operators, but ConfigCat allows multiple attribute values (an array of strings) for the ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF comparators only. This means that it's not possible to specify multiple values for a user attribute if the evaluated feature flag contains a [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md) that references the attribute, but has a comparator other than the two mentioned. Unfortunately, no workaround exists for this case.
7. Rewrite feature flag evaluation calls.
This step is pretty straightforward as ConfigCat SDKs provide similar evaluation methods to LaunchDarkly SDKs. Those methods are named `getValue`, `getValueAsync` or similar.
A few things to pay attention to:
* The order of parameters is different. In ConfigCat, the User Object comes last.
* The ConfigCat feature flag key may be different from the LaunchDarkly one. E.g. if the key starts with a non-letter character, or contains a dot, it will be changed by the import tool because such keys are not valid in ConfigCat. To see which keys have been changed, look for [T002](https://configcat.com/docs/advanced/migration-from-launchdarkly-translation.md#translation-issue-T002) translation issues in the report.
* ConfigCat SDKs don't support [automatic camel casing](https://launchdarkly.com/docs/sdk/client-side/react/react-web#flag-keys-in-the-react-web-sdk) of feature flag keys.
* In statically typed languages, ConfigCat evaluation methods require that the default value type and the feature flag type match. (Usually, there is [a section about this](https://configcat.com/docs/sdk-reference/js/overview.md#setting-type-mapping) in the SDK reference.)
* Please be extra careful when evaluating number type feature flags. ConfigCat distinguishes between integer and decimal number feature flags. The former must be evaluated using `getValue`, `getIntValue` or similar, while the latter must be evaluated using `getValue`, `getDoubleValue` or similar. (JavaScript-based SDKs don't have this issue, but you can run into it in other languages.)
* On some platforms, the ConfigCat client provides asynchronous evaluation methods only. In such cases, synchronous feature flag evaluation is usually still possible, [via snapshots](https://configcat.com/docs/sdk-reference/js/overview.md#snapshots-and-synchronous-feature-flag-evaluation). But this works slightly differently from the asynchronous methods, so make sure you understand its behavior and possible pitfalls.
By adjusting the example code according to the above, we get this:
```js
import configcat from "configcat-node";
const sdkKey = process.env.CONFIGCAT_SDK_KEY ?? "#YOUR-SDK-KEY#";
const client = configcat.getClient(sdkKey, configcat.PollingMode.AutoPoll, {
maxInitWaitTimeSeconds: 10
});
const clientCacheState = await client.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
console.error("SDK failed to initialize.");
process.exit(1);
}
const user = {
identifier: "#UNIQUE-USER-IDENTIFIER#",
email: "alice@example.com",
country: "UK",
custom: {
"name": "Alice",
"organization:key": "#UNIQUE-ORG-IDENTIFIER#",
"organization:/address/city": "London",
"/kind": ["user", "organization"],
}
};
const flagValue = await client.getValueAsync("isAwesomeFeatureEnabled", false, user);
if (flagValue) {
console.log("Feature is enabled.")
} else {
console.log("Feature is disabled.")
}
process.exit(0);
```
The conversion can be done in a similar way on other platforms as well. Obviously, there may be minor differences, plus advanced topics are not covered here, so it's recommended to start this work by going through the SDK reference for your platform.
##### Adjust a codebase that uses OpenFeature[](#adjust-a-codebase-that-uses-openfeature "Direct link to Adjust a codebase that uses OpenFeature")
You should have an easier time if feature flagging is done using the [OpenFeature](https://openfeature.dev/docs/reference/intro/) abstraction in your applications.
In this case, please check [this list](https://configcat.com/docs/sdk-reference/openfeature/overview/) to see if a ConfigCat OpenFeature provider is available for your platform.
If you're out of luck, you can still use the ConfigCat SDK directly as explained in the previous section, or [contact us](https://configcat.com/support) about the missing OpenFeature provider.
Otherwise, to switch to ConfigCat, you need to do the following:
1. Uninstall the LaunchDarkly OpenFeature provider package, and install the ConfigCat one instead.
2. Adjust the initialization logic.
Look for a call to `setProvider`, `setProviderAndWait` or similar, and change it so an instance of ConfigCat OpenFeature provider is passed to it. (For ConfigCat, use `setProviderAndWait` if possible.)
3. Convert [LaunchDarkly-specific evaluation context objects](https://github.com/launchdarkly/openfeature-node-server?tab=readme-ov-file#openfeature-specific-considerations) to have a data structure compatible with ConfigCat.
This is done in a very similar way to what's described in the previous section. Read [this section](https://configcat.com/docs/advanced/migration-from-launchdarkly-translation.md#mapping-between-launchdarkly-contexts-and-configcat-user-objects) to learn how context paths are mapped to User Object attribute names.
For example, something like
```js
const evaluationContext = {
kind: "multi",
user: {
targetingKey: "#UNIQUE-USER-IDENTIFIER#",
name: "Alice",
email: "alice@example.com",
country: "UK"
},
organization: {
targetingKey: "#UNIQUE-ORG-IDENTIFIER#",
address: {
city: "London"
}
}
};
```
should be converted to this:
```js
const evaluationContext = {
targetingKey: "#UNIQUE-USER-IDENTIFIER#",
name: "Alice"
email: "alice@example.com",
country: "UK",
"organization:key": "#UNIQUE-ORG-IDENTIFIER#",
"organization:/address/city": "London",
"/kind": ["user", "organization"],
};
```
4. Review feature flag evaluation calls.
Most of the pitfalls pointed out in the "Rewrite feature flag evaluation calls" part of the previous section applies here too.
##### Implement experiments and analytics[](#implement-experiments-and-analytics "Direct link to Implement experiments and analytics")
There are some fundamental differences in the feature flag evaluation process between LaunchDarkly and ConfigCat. In ConfigCat, feature flag evaluation is entirely implemented within the SDKs, meaning your users' sensitive data never leaves your system. The data flow is one-way – from ConfigCat CDN servers to your SDKs – and ConfigCat does not receive or store any attributes of the [User Object](https://configcat.com/docs/targeting/user-object.md) passed to the SDKs. This design prioritizes the privacy and security of user data.
However, this has an important consequence: as opposed to LaunchDarkly, ConfigCat cannot provide an out-of-the-box solution to A/B testing, experiments or other analytics.
For this, you will need an additional service that provides the necessary functionality. Here are some examples of how you can integrate such tools with ConfigCat to replicate LaunchDarkly's analytics features:
* [Amplitude](https://configcat.com/docs/integrations/amplitude.md#experiments)
* [Google Analytics](https://configcat.com/docs/integrations/google-analytics.md)
* [Mixpanel](https://configcat.com/docs/integrations/mixpanel.md#experiments)
* [Twilio Segment](https://configcat.com/docs/integrations/segment.md#analytics)
#### Migrate LaunchDarkly teams and permissions to ConfigCat[](#migrate-launchdarkly-teams-and-permissions-to-configcat "Direct link to Migrate LaunchDarkly teams and permissions to ConfigCat")
To complete the migration process, you will also need to migrate your teams and permissions from LaunchDarkly.
At the moment, ConfigCat doesn't offer a tool or other automated solution for this task since there are fundamental differences between the user management and permission systems of the two services.
LaunchDarkly allows more fine-grained access control over resources, while ConfigCat's permission system was designed to be simpler and easier to understand, at the expense of fewer possibilities for fine-tuning access control.
Therefore, we can only give you some pointers, but this task will inevitably require some effort on your part.
As the first step, we recommend getting familiar with ConfigCat's user management and permission system. You can find the basic concepts in the following guides:
* [Organization & Roles](https://configcat.com/docs/organization.md)
* [Team Management Basics](https://configcat.com/docs/advanced/team-management/team-management-basics.md)
As you can see from this, ConfigCat doesn't use the concept of teams and roles of LaunchDarkly. You can't define such entities at the organization level, but *permission groups* per product instead.
##### Map LaunchDarkly roles to ConfigCat permission groups[](#map-launchdarkly-roles-to-configcat-permission-groups "Direct link to Map LaunchDarkly roles to ConfigCat permission groups")
Permission groups roughly correspond to LaunchDarkly roles, with a few key differences:
* They are scoped to the product where they are defined.
* There are no [built-in roles](https://launchdarkly.com/docs/home/account/built-in-roles) like Reader or Writer. To recreate these in ConfigCat, you will need to define the corresponding permission groups in each relevant product. However, LaunchDarkly's Admin and Owner roles can't really be represented using permission groups. ConfigCat supports the concept of [Organization Admin role](https://configcat.com/docs/organization.md#organization-admin-role) but it's an organization-level permission. You can assign this to users on invite or on your organization's "Members & Roles" page as shown in the next section.
* To migrate [custom roles](https://launchdarkly.com/docs/home/account/custom-roles) to ConfigCat, you will need to translate the [policies](https://launchdarkly.com/docs/home/account/role-concepts#policies) they define to the fixed set of permissions offered by ConfigCat permission groups. Obviously, this won't be entirely possible in every case.
With this in mind, create the necessary permission groups in your products, based on the roles defined in your LaunchDarkly organization.
To set up permission groups for a product, open the [ConfigCat Dashboard](https://app.configcat.com/organization), select the product on the sidebar, and choose "Permission Groups" in the top menu.

##### Invite users to ConfigCat and assign them to permission groups[](#invite-users-to-configcat-and-assign-them-to-permission-groups "Direct link to Invite users to ConfigCat and assign them to permission groups")
Permission groups also act as per-product teams. Once created, you can assign users to them, who will then have the permissions specified by the permission group. (A user can only be a member of a single permission group at a time though.) This is how you map your LaunchDarkly teams to ConfigCat.
However, users don't yet exist in ConfigCat at this point. You need to invite them to ConfigCat first. To do this, follow [these instructions](https://configcat.com/docs/advanced/team-management/team-management-basics.md#invite-others-to-collaborate).
When inviting users, you will need to choose a product, more specifically, a permission group to invite them to. This means that they will be automatically assigned to the specified permission groups after signing up. So, as you have already created the permission groups, ideally you can immediately invite your users to the right permission groups. (Of course, you may need to do this in batches.)
It can easily happen that you want to add a user to more than one product. In such cases, invite the user to one of the products (it doesn't matter which one), then, after they've signed up, navigate to the "Members & Roles" page of your organization, and assign them to the other products too, using the "Change roles" feature of the "Members & Roles" table.

---
### Details of LaunchDarkly to ConfigCat Translation
Copy page
This document discusses the details of how [ConfigCat's "Import from LaunchDarkly" tool](https://configcat.com/docs/advanced/migration-from-launchdarkly.md#migrate-launchdarkly-feature-flags-and-segments-to-configcat) translates LaunchDarkly projects to ConfigCat products (i.e., how, in practice, the import tool converts the project data fetched fromLaunchDarkly's REST API to ConfigCat's Export/Import JSON format).
You need this information if you want to understand
* why the import tool produces the result that it does,
* what issues can arise during translation, and how to solve them,
* what the limitations of translation are.
#### Mapping between LaunchDarkly and ConfigCat entities[](#mapping-between-launchdarkly-and-configcat-entities "Direct link to Mapping between LaunchDarkly and ConfigCat entities")
The table below shows how LaunchDarkly entities are mapped to ConfigCat entities.
| LaunchDarkly entity | Corresponding ConfigCat entity | Notes |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| project | [product](https://configcat.com/docs/main-concepts.md#product) | |
| environment | [environment](https://configcat.com/docs/main-concepts.md#environment) | |
| segment | [segment](https://configcat.com/docs/targeting/targeting-rule/segment-condition.md#what-is-a-segment-condition-what-is-a-segment) | LaunchDarkly segments are specific to an environment, but ConfigCat segments are specific to a product, so mapped segment names are prefixed with the environment name to avoid ambiguity. |
| feature flag | [feature flag / setting](https://configcat.com/docs/targeting/targeting-overview.md#feature-flag--setting) | LaunchDarkly feature flags are directly contained by a project, but ConfigCat feature flags are organized into [configs](https://configcat.com/docs/main-concepts.md#config), so a config named "Main Config" is created to contain them. |
| targeting toggle | - | No direct translation is possible. More on this [here](https://configcat.com/docs/advanced/migration-from-launchdarkly.md#targeting-toggle-translation-mode). |
| prerequisites | - | Each prerequisite is translated to a [Targeting Rule](https://configcat.com/docs/targeting/targeting-overview.md#targeting-rule) containing a [Flag Condition](https://configcat.com/docs/targeting/targeting-rule/flag-condition.md). |
| individual targets | - | Each target group is translated to a [Targeting Rule](https://configcat.com/docs/targeting/targeting-overview.md#targeting-rule) containing an IS ONE OF [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md). |
| custom rule | [Targeting Rule](https://configcat.com/docs/targeting/targeting-overview.md#targeting-rule) | Multiple clauses (i.e. [AND conditions](https://configcat.com/docs/targeting/targeting-rule/targeting-rule-overview.md#and-and-or-relationships) in ConfigCat's terminology) are not supported for segments, only for feature flags at the moment. |
| custom rule clause | [User Condition](https://configcat.com/docs/targeting/targeting-rule/user-condition.md) or [Segment Condition](https://configcat.com/docs/targeting/targeting-rule/segment-condition.md) | Some LaunchDarkly clauses cannot be translated to ConfigCat conditions with the same evaluation behavior, or at all. See also [translation issues](#translation-issues) |
| clause attribute reference | [comparison attribute](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparison-attribute) | LaunchDarkly context attribute paths don't always translate to ConfigCat user attribute names directly. See also [this section](#mapping-between-launchdarkly-contexts-and-configcat-user-objects). |
| clause operator | [comparator](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparator) | Most LaunchDarkly operators have their counterparts in ConfigCat (there can be minor or major differences between them though), but a few operators are not supported by ConfigCat at all (e.g. "matches" / "does not match"). |
| clause values | [comparison value](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#comparison-value) | As opposed to LaunchDarkly, not all counterparts of operators support multiple values. |
| percentage rollout | [Percentage Options](https://configcat.com/docs/targeting/percentage-options.md) | In LaunchDarkly, the basis of the grouping can be set for each percentage rollout, while in ConfigCat [Percentage Evaluation Attribute](https://configcat.com/docs/targeting/percentage-options.md#percentage-evaluation-attribute) can only be set at the feature flag level. |
| default rule | [trivial / fallback rule](https://configcat.com/docs/targeting/targeting-overview.md#to-all-users--to-all-other--to-unidentified-value) | |
#### Mapping between LaunchDarkly contexts and ConfigCat User Objects[](#mapping-between-launchdarkly-contexts-and-configcat-user-objects "Direct link to Mapping between LaunchDarkly contexts and ConfigCat User Objects")
Both LaunchDarkly and ConfigCat support passing user and/or session-related contextual information to feature flag evaluation, which is essential for targeting: LaunchDarkly offers [contexts](https://launchdarkly.com/docs/home/observability/contexts), while ConfigCat offers [User Objects](https://configcat.com/docs/targeting/user-object.md) for this purpose.
However, the data structure of these is different:
* In LaunchDarkly, in addition to the default user context, it is possible to define and use other, arbitrary contexts (e.g. device, application, etc.). [Multi-contexts](https://launchdarkly.com/docs/home/flags/multi-contexts) and nested objects are also possible.
* On the contrary, ConfigCat's User Object is a simpler data structure, primarily designed for storing user-related information. However, via custom attributes it's still able to store arbitrary information.
On top of that, LaunchDarkly context attributes are identified by the combination of a context kind and a path expression, while ConfigCat uses simple attribute names. For this reason, it is necessary to define an unambiguous mapping between the two.
This is done as shown in the following table:
| LaunchDarkly context kind | LaunchDarkly context attribute path | Corresponding ConfigCat user attribute name |
| ------------------------- | ----------------------------------- | ------------------------------------------- |
| not specified or `user` | empty string or `/` | `/` |
| not specified or `user` | `key` or `/key` | `Identifier` |
| not specified or `user` | `email` or `/email` | `Email` |
| not specified or `user` | `country` or `/country` | `Country` |
| not specified or `user` | `Identifier` or `/Identifier` | `/Identifier` |
| not specified or `user` | `Email` or `/Email` | `/Email` |
| not specified or `user` | `Country` or `/Country` | `/Country` |
| not specified or `user` | `name` or `/name` | `name` |
| not specified or `user` | `/address/city` | `/address/city` |
| `device` | empty string or `/` | `device:/` |
| `device` | `name` or `/name` | `device:name` |
| `organization` | `name` or `/name` | `organization:name` |
| `organization` | `/address/city` | `organization:/address/city` |
| any | `kind` or `/kind` | `/kind` |
Please note that:
* Both LaunchDarkly context attribute paths and ConfigCat user attribute names are case-sensitive.
* In ConfigCat, `Identifier`, `Email` and `Country` are predefined attributes. Everything else qualifies as custom attributes.
* One-component LaunchDarkly attribute path expressions are always normalized to their unescaped form if possible. E.g. `/~0~1x` → `~/x`, but `/~1~00` → `/~1~00` (as `/~0` would be an ambiguous mapping).
* Multi-component LaunchDarkly attribute path expressions are kept as is (unless they contain `:` characters - see below).
* Context kinds other than `user` are included as a prefix in the mapped ConfigCat user attribute name, with `:` as the separator. Because of this, LaunchDarkly context attribute paths containing `:` characters needs to be escaped to avoid ambiguity. E.g. `a:b` -> `/a~;b`, `/a:b` -> `/a~;b`.
#### Translation issues[](#translation-issues "Direct link to Translation issues")
There are technical differences between LaunchDarkly and ConfigCat, therefore it's not always possible to translate all entities accurately, i.e. so that they are represented identically in ConfigCat, and provide equivalent behavior to the original. (By equivalent behaviour we primarily mean equivalent evaluation behaviour, i.e. that the evaluation of a feature flag or segment produces the same result for the same input parameters.)
Such problematic cases are called *translation issues*, and a *severity level* is assigned to them as follows.
🔴 HIGH - The imported entity cannot provide equivalent behavior to the original at all. 🟡 MEDIUM - The imported entity may not provide equivalent behavior to the original in every case. 🔵 LOW - The imported entity does not exactly reflect the original in some way, but it is expected to provide equivalent behavior to the original.
The tables below show the possible translation issues.
##### Limitations[](#limitations "Direct link to Limitations")
info
Usually these issues arise when you are on a lower plan, and hitting a subscription limit. If that's the case, feel free to [contact us](https://configcat.com/support/?prefilled=ld-import-limit), we are happy to raise your limits temporarily so you can fully explore the product and evaluate it at your pace.
| Code | Level | Issue | What can be the cause? | How is it handled? |
| ---- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| L001 | 🔴 HIGH | The number of Targeting Rules resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | There are too many rules in the original feature flag. | As many LaunchDarkly rules as the limit allows are imported, but the rest is omitted. |
| L002 | 🔴 HIGH | The number of conditions resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | There are too many clauses in a rule of the original feature flag. | As many LaunchDarkly clauses as the limit allows are imported, but the rest is omitted. |
| L003 | 🔴 HIGH | The number of percentage options resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | There are too many percentage rollout variations in the original feature flag. | As many LaunchDarkly percentage rollout variations as the limit allows are imported, but the rest is omitted. The percentage of the last imported item is adjusted so that the sum of percentages equals 100%. |
| L004 | 🔴 HIGH | The length of a comparison value resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | The value(s) of a LaunchDarkly clause translate to a string comparison value that would be too long. | The comparison value is truncated so that it fits within the limit. |
| L005 | 🔴 HIGH | The number of items in a comparison value list resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | The values of a clause translate to a comparison value list that would have too many items. | The comparison value list is truncated so that it fits within the limit. |
| L006 | 🔴 HIGH | The length of an item in a comparison value list resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | One or more values of a clause translate to a comparison value item that would be too long. | The comparison value item is truncated so that it fits within the limit. |
| L007 | 🔴 HIGH | The length of a text setting value resulting from the translation would exceed the [subscription / technical limit](https://configcat.com/docs/subscription-plan-limits.md). | A feature flag variation value translates to a text setting value that would be too long. | The text setting value is truncated so that it fits within the limit. |
##### Technical differences[](#technical-differences "Direct link to Technical differences")
| Code | Level | Issue | What can be the cause? | How is it handled? |
| ---- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| T001 | 🔵 LOW | A project, environment, segment or feature flag was imported under a different name than the original. | 1. LaunchDarkly project, environment and segment names do not have to be unique (since those items always have a unique key in LaunchDarkly too). The corresponding ConfigCat entities, however, must have a case-insensitive unique name. 2. LaunchDarkly allows longer names than ConfigCat. | 1. In the case of identical names, the LaunchDarkly unique key is included in the name. If this is still not unique, then a number suffix is added as well. 2. Names that are too long are truncated at the maximum length. If this results in a conflicting name, it is made unique by adding a number suffix. |
| T002 | 🟡 MEDIUM | A feature flag was imported with a different key than the original. | 1. Feature flag keys are unique in both systems, but they must be case sensitive in LaunchDarkly and case insensitive in ConfigCat. 2. As opposed to LaunchDarkly, ConfigCat feature flag keys are not allowed to start with a number or contain dots. 3. Depending on the Targeting Toggle Translation Mode option, the targeting toggle may be emulated using an extra prerequisite flag. The key for this is generated by adding the suffix `_tt` to the key of the main flag. | 1. Conflicts are resolved by adding a number suffix. 2. Characters that are invalid in ConfigCat are replaced with `_`. If the first character is not a letter, the prefix `x_` is also added to the key. If this results in a conflicting key, it is made unique by adding a number suffix. 3. Conflicts are resolved by adding a number suffix. (But always the uniqueness of the the actually imported flags' keys are ensured first.) |
| T003 | 🔵 LOW | A feature flag tag name was truncated. | LaunchDarkly may allow longer tag names than ConfigCat. | Names that are too long are truncated at the maximum length. If this results in a conflicting name, no effort is made to make it unique. |
| T004 | 🔵 LOW | A JSON feature flag was encountered. | LaunchDarkly allows feature flags with JSON values, but ConfigCat doesn't support that directly at the moment. | A text setting is created in ConfigCat, with values containing the JSON variation values serialized to text. It is your responsibility to deserialize the text once returned by feature flag evaluation. |
| T005 | 🟡 MEDIUM | A comparison attribute name was truncated. | A context attribute name is mapped to a user attribute name that is too long. | The comparison attribute name is truncated so that it fits within the limit. If this results in a conflicting name, no effort is made to make it unique. |
| T006 | 🔴 HIGH | Unset off variation was encountered. | In LaunchDarkly, it is not required to set a variation for the case when targeting is turned off. In that case, feature flag evaluation will return the default value you pass to the LaunchDarkly SDK. There is no way to reproduce this behavior in ConfigCat. | There is no way to emulate this behavior in ConfigCat, so a placeholder value is used as follows:- boolean flag: `false` - string flag: `"_"` - json flag: `"null"` - number flag: 0 |
| T007 | 🔵 LOW | Targeting is turned off, and the targeting toggle was respected. | Targeting Toggle Translation Mode option was set to "Respect targeting toggle and don't import rules", and1. targeting is turned off for the feature flag in the specific environment, 2. or targeting is turned off for one or more prerequisites in the specific environment (see also the "Prerequisite flags must be on" section in [this article](https://launchdarkly.com/docs/home/flags/prereqs)). | A single Targeting Rule that returns the off variation is created in ConfigCat, and the actual rules are not imported for the specific environment. (The imported feature flag will work as it does in LaunchDarkly at the time of import.) |
| T008 | 🟡 MEDIUM | Targeting is turned off, and the targeting toggle was ignored. | Targeting Toggle Translation Mode option was set to "Ignore targeting toggle and import rules anyway", and1. targeting is turned off for the feature flag in the specific environment, 2. or targeting is turned off for one or more prerequisites in the specific environment (see also the "Prerequisite flags must be on" section in [this article](https://launchdarkly.com/docs/home/flags/prereqs)). | The off variation is ignored, and the actual rules are imported for the specific environment. (The imported feature flag will not work as it does in LaunchDarkly at the time of import.) |
| T009 | 🔴 HIGH | A segment clause references multiple segments, but cannot be translated due to subscription / technical limit. | ConfigCat doesn't support referencing multiple segments in Segment Conditions. There is a workaround though: non-negated LaunchDarkly clauses can be expanded into multiple ConfigCat Targeting Rules, negated LaunchDarkly clauses can be expanded into multiple ConfigCat conditions. However, in the specific case the expansion is not possible because of subscription / technical limits. | A Segment Condition is created in ConfigCat but it references the first segment only. The rest of the segment references are omitted. |
| T010 | 🔴 HIGH | A segment that references another segment was encountered. | ConfigCat segments do not support targeting segments. | A placeholder condition is created in ConfigCat. |
| T011 | 🔴 HIGH | An untranslatable clause was encountered in a feature flag or segment rule. | The LaunchDarkly clause is not translatable to a ConfigCat condition, not even via a workaround. Such cases are:1. Feature flag or segment rule clause uses the "matches" / "does not match" operators. 2. Feature flag rule clause is based on Context kind but cannot be translated to an ARRAY IS (NOT) ONE OF condition. 3. Segment rule clause is based on Context kind. 4. Segment rule clause uses the "starts with" / "does not start with" / "ends with" / "does not end with" operators. 5. Segment rule clause uses the "before" or "after" operator. 6. Feature flag or segment rule targets application versions (no such feature in ConfigCat). | A placeholder condition is created in ConfigCat. |
| T012 | 🔵 LOW | A clause was translated to multiple Targeting Rules or conditions. | Some LaunchDarkly clauses like segment clauses referencing multiple segments cannot be directly translated to a single ConfigCat condition. However, in the specific case, a workaround that provides logically equivalent evaluation behavior is possible. | If the LaunchDarkly clause is non-negated, it is expanded into multiple ConfigCat Targeting Rules, otherwise it is expanded into multiple ConfigCat conditions. |
| T013 | 🔴 HIGH | A "contains" / "does not contain" segment clause with multiple values was encountered. | In segments, the ConfigCat counterparts of the "contains" / "does not contain" operators only accept a single comparison value at the moment. | The clause is translated to a CONTAINS / DOES NOT CONTAIN segment, however only the first clause value is preserved. The rest of the values are omitted. |
| T014 | 🔵 LOW | A "<", "<=", ">", ">=", "SemVer <", "SemVer <=", "SemVer >", "SemVer >=" or "before" / "after" clause with multiple values was encountered. | The ConfigCat counterpart of these operators allows a single comparison value only. | Multiple comparison values are reduced to a single one. (This can be done in such a way that the clause remains logically accurate.) The rest of the values are omitted though. It is also worth noting that the evaluation behavior of "SemVer <=" and "SemVer >=" clauses with multiple values is inconsistent with similar operators in LaunchDarkly. So, since translation preserves the inconsistent behavior, it may produce surprising results in such cases. |
| T015 | 🟡 MEDIUM | A "Context kind is (not) one of" clause was encountered. | In ConfigCat, there is no such concept as contexts and context kinds. ConfigCat SDKs won't automatically provide context kinds as an attribute via the User Object. | An ARRAY IS (NOT) ONE OF condition is created in ConfigCat, but it is your responsibility to pass the context kind values to the ConfigCat SDK via the custom user attribute named `/kind`. |
| T016 | 🟡 MEDIUM | A mobile targeting-related clause was encountered. | For mobile apps, LaunchDarkly allows targeting special, [automatically provided context attributes](https://launchdarkly.com/docs/sdk/features/environment-attributes) of context kinds `ld_application` and `ld_device`. ConfigCat SDKs won't automatically provide these attributes via the User Object. | The clause is translated, but it is your responsibility to pass the attribute values to the ConfigCat SDK via custom user attributes. |
| T017 | 🟡 MEDIUM | A not accurately translatable "is (not) one of" clause was encountered. | In LaunchDarkly, "is (not) one of" clauses can work with string, boolean and number values, but their ConfigCat counterparts can work with strings only. This can be a problem in two cases:1. "is (not) one of" clauses with boolean comparison values cannot be translated accurately as ConfigCat offers no comparators that work with boolean values at the moment, 2. "is (not) one of" clauses with number comparison values may be translated accurately using the = (number) / != (number) comparators. These accept a single comparison value though, so clauses with multiple values must be expanded into multiple targeting rules or conditions, depending on negation. However, in the specific case the expansion is not possible because of subscription / technical limits. | An IS (NOT) ONE OF condition is created in ConfigCat and the non-string values are converted to string. From the perspective of feature flag evaluation this means the following: the ConfigCat SDK will convert non-string user attributes to string, and do case-sensitive string comparisons when evaluating the feature flag. In the case of boolean and decimal number values this can lead to undesired behavior. E.g. on some platforms, the ConfigCat SDK may convert the false boolean value to the string `False`, which won't be matched by an IS ONE OF condition having a comparison value `false`. Similarly, there could be subtle differences in decimal number to string conversion across various platforms. |
| T018 | 🔵 LOW | One or more variations of a percentage rollout had to be omitted. | LaunchDarkly includes all the feature flag variations in a percentage rollout even if most of them are set 0%. However, this could lead to exceeding the subscription limit on Percentage Options in ConfigCat (especially, on lower plans). | As variations set to 0% don't affect the evaluation of the imported Percentage Options, translation omits as many of them as needed to fit within the limit. |
| T019 | 🟡 MEDIUM | One or more percentage values of a percentage rollout had to be adjusted. | As opposed to LaunchDarkly, ConfigCat doesn't allow fractional percentage values in Percentage Options. | Non-integer percentage values are rounded. This may also cause the sum of the percentage values to over or undershoot 100%. In such cases, further adjustments are performed to make the sum exactly 100%. |
| T020 | 🔴 HIGH | There are multiple percentage rollout rules in the feature flag, but they do not use the same attribute as the basis of the rollout. | In LaunchDarkly, it is possible to set different attributes as the basis of the rollout for each percentage rollout rule. In ConfigCat, this can only be set at the feature flag level. | There is no workaround. The attribute that occurs the most times is set as the flag's Percentage Evaluation Attribute. |
| T021 | 🔴 HIGH | A segment with no rules was encountered. | LaunchDarkly allows segments to have no rules, while ConfigCat segments specify exactly one rule. | A segment with a placeholder condition is created in ConfigCat. |
| T022 | 🔴 HIGH | A segment with multiple rules was encountered. | LaunchDarkly allows segments to have multiple rules, while ConfigCat segments specify exactly one rule. | A segment is created in ConfigCat, with a translation of the first rule only. The rest of the rules are omitted. |
| T023 | 🔴 HIGH | A segment rule with multiple clauses was encountered. | LaunchDarkly allows multiple clauses in segment rules, while ConfigCat doesn't support AND conditions in segments at the moment. | There is no workaround. Clauses except for the first one are omitted. |
| T024 | 🔴 HIGH | A segment rule with percentage targeting was encountered. | LaunchDarkly allows segment rules to include a percentage of targets only. ConfigCat segments doesn't offer such feature. | There is no workaround. The percentage targeting part is ignored. |
| T025 | 🔴 HIGH | A segment rule was only partially translated. | Translating the segment rule would require multiple rules in ConfigCat, which is not supported. | The segment rule is only partially imported. |
| T026 | 🔴 HIGH | A big segment was encountered. | Big segments are not supported by ConfigCat. | A normal segment with a hint about the issue is created in ConfigCat. |
| T027 | 🔴 HIGH | Comparison value list item contains comma. | In the case of segments, multiple clause values translate to a comma separated comparison value list. There is no way to escape the comma, so it must be replaced with another character, otherwise values containing a comma would be interpreted as multiple items. | Comma is replaced with semicolon in comparison value list items. |
| T028 | 🔴 HIGH | A feature flag variation value was changed. | LaunchDarkly allows variation values that are not valid in ConfigCat. More specifically, the empty string in the case of string feature flags. | Problematic variation values are changed into valid ConfigCat values, and if necessary, they are made unique by adding a number suffix. |
| T029 | 🔵 LOW | A feature flag variation name was changed. | LaunchDarkly may allow longer variation names than ConfigCat. Also, LaunchDarkly enforces looser rules than ConfigCat with regard to variation name uniqueness. | Names that are too long are truncated at the maximum length. Then the effective name (the truncated name or, if no name is specified, the variation value) is checked for conflicts, and if necessary, it is made unique by adding a number suffix. |
##### Data consistency[](#data-consistency "Direct link to Data consistency")
| Code | Level | Issue | What can be the cause? | How is it handled? |
| ---- | --------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| D001 | 🔴 HIGH | The data model fetched from LaunchDarkly contains invalid, inconsistent or unexpected data. | In theory, such a thing cannot happen, but in practice it cannot be excluded. | Obviously, the import tool cannot produce a correct result from an inherently incorrect input. As a best effort, it generates a valid import model so that the import operation can go through, and you can review and fix the problematic entities. |
| D002 | 🟡 MEDIUM | The feature flag was modified in LaunchDarkly while the feature flag data was being fetched. | Due to the peculiarities of the LaunchDarkly REST API, the full data model of a feature flag can only be queried for a single environment per a single request. So, it may happen that some non-environment-related properties of the feature flag are modified while fetching the feature flag data (e.g. name, variations, etc.) In such cases, inconsistencies across environments are possible in the retrieved data. | The import tool can only detect inconsistencies, but cannot do anything about them. Please check whether the imported feature flag is set correctly in each environment. Alternatively, you may try to re-import the specific feature flag. |
#### Further technical differences[](#further-technical-differences "Direct link to Further technical differences")
* As opposed to LaunchDarkly, ConfigCat distinguishes between integer and decimal number feature flags. Therefore, when translating number feature flags, the ConfigCat setting type is guessed based on the variation values specified at the time of the import.
* For percentage rollouts, LaunchDarkly and ConfigCat use different algorithms to split users into groups. That is, even if the percentage values are the same, the distribution of users will be different. In other words, [stickiness](https://configcat.com/docs/targeting/percentage-options.md#stickiness) of percentage rollouts cannot be transferred to ConfigCat.
* In the case of percentage rollouts within custom rules, evaluation behavior is different between the two services when the attribute used as the basis of the percentage rollout is not provided (i.e. not passed to the SDK on evaluation):
* LaunchDarkly will serve the value of the first variation whose percentage value is not 0%.
* ConfigCat will skip the targeting rule and continue evaluation with the next rule.
* In LaunchDarkly, all clause operators can work with context attribute value lists. In ConfigCat, most of the comparators (counterparts of operators) can work with a single user attribute only. The only exceptions is ARRAY IS (NOT) ONE OF.
* In LaunchDarkly, it is possible to control whether or not specific feature flags are visible to mobile and/or client-side SDKs ([Client-side SDK availability](https://launchdarkly.com/docs/home/flags/new#make-flags-available-to-client-side-and-mobile-sdks)). There is no such feature in ConfigCat, so this preference is ignored. All the feature flags are imported into a single config which can be accessed by all kinds of ConfigCat SDKs.
* In LaunchDarkly, it is possible to mark a feature flag as temporary or permanent. There is no such feature in ConfigCat. Yet translation preserves this piece of information by adding a tag to the feature flag.
* In LaunchDarkly, it is possible to assign a name to the variations (possible outcomes of the feature flag). There is no such feature in ConfigCat at the moment, so these pieces of information are not transferred.
---
### Notifications - Webhooks
Copy page
ConfigCat Webhooks can notify your applications when a feature flag or other Setting changes by calling a public HTTP endpoint on your end. This allows your applications to react almost immediately to updates. Webhooks add the speed of near real-time updates to the reliability of Polling, giving your applications a fast and robust way to stay in sync. To enable Webhooks, simply tell us which HTTP endpoint to call. ConfigCat will send a request to that URL whenever a change occurs.
#### Adding a Webhook[](#adding-a-webhook "Direct link to Adding a Webhook")
1. Go to the [Webhooks](https://app.configcat.com/webhook) screen.
2. Click the **+ ADD WEBHOOK** button.
3. Choose **when** webhook notifications should be sent by selecting the **Config** and **Environment** where changes should trigger the Webhook.
4. Define **how** to notify your system by setting the **URL** and the **HTTP METHOD**. This tells us which endpoint to call.
5. (Optional) Add custom HTTP headers and a request body if needed.
#### Request body with variables[](#request-body-with-variables "Direct link to Request body with variables")
You can customize the request body that will be sent with each Webhook call. ConfigCat will replace certain placeholders in the body with real values at runtime.
| Variable | Replaced with |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **##ConfigName##** | The name of the Config where the change happened. |
| **##ConfigId##** | ID of the Config where the change happened. |
| **##EnvironmentName##** | The name of the Environment where the change happened. |
| **##EnvironmentId##** | ID of the Environment where the change happened. |
| **##URL##** | A direct link to the Config in the *ConfigCat Dashboard.* |
| **##ChangeNotes##** | The **Mandatory notes** added to the actual changeset. |
| **##ChangedBy##** | The name and email address of the user who made the changes. |
| **##ChangeDetails##** | Detailed change info in JSON format, including the name of the Setting or feature flag, old and new values and Targeting Rules. |
| **##ChangeDetailsTeams##** | Change details formatted for Microsoft Teams. |
| **##ChangeDetailsSlack##** | Change details formatted for Slack. |
The ##ChangeDetails## variable is replaced with a JSON array in the following format:
```text
[
{
"settingKey":"myAwesomeFeature1",
"event":"changed",
"details":"\r\nmyAwesomeFeature1: false ➔ true"
},
{
"settingKey":"myAwesomeFeature2",
"event":"changed",
"details":"\r\nmyAwesomeFeature2:\r\n Rollout percentage items changed:\r\n + 20% true\r\n + 80% false"
}
]
```
#### Testing your Webhook[](#testing-your-webhook "Direct link to Testing your Webhook")
1. Change some of your settings in the *ConfigCat Dashboard.*
2. Click **SAVE & PUBLISH CHANGES**.
3. Check if your Webhook was called correctly.
info
**Developer Tip**
* Running your Webhook on `localhost`? Expose it to the public internet temporarily by using a tool like [ngrok](https://ngrok.com/). This enables ConfigCat to call your webhook even in your local development environment.
* Just interested in what ConfigCat sends? Try [Webhhok.site](https://webhook.site/). This allows you to catch HTTP requests and see their content without requiring your to run anything anywhere.
#### Verifying Webhook requests[](#verifying-webhook-requests "Direct link to Verifying Webhook requests")
To make sure the requests you receive are actually sent by ConfigCat, we strongly recommend verifying the signature included in the request headers. You can do this by comparing the received signature with one you compute using your signing key.
Each webhook request includes the following headers:
| Header | Description |
| ---------------------------------- | -------------------------------------------------------------------------------------------- |
| `X-ConfigCat-Webhook-ID` | A unique ID for the webhook request. This is different for every request. |
| `X-ConfigCat-Webhook-Timestamp` | The time the request was sent, in Unix timestamp format (seconds since epoch). |
| `X-ConfigCat-Webhook-Signature-V1` | A comma-separated list of base64-encoded HMAC-SHA-256 signatures (one for each signing key). |
Currently, the latest (and the only) signature header version is `V1`. If the signing process changes in the future, new headers will be added with incremented version numbers.
Example request:
```text
POST /path HTTP/1.1
Host:
X-ConfigCat-Webhook-ID: b616ca659d154a5fb907dd8475792eeb
X-ConfigCat-Webhook-Timestamp: 1669580020
X-ConfigCat-Webhook-Signature-V1: RoO/UMvSRqzJ0OolMMuhHBbM8/Vjn+nTh+SKyLcQf0M=,heIrGPw6aylAZEX6xmSLrxIWVif5injeBCxWQ+0+b2U=
```
##### Content to sign[](#content-to-sign "Direct link to Content to sign")
The signature is calculated from the content constructed by concatenating the webhook's `id`, `timestamp`, and raw `body` together.
```js
const contentToSign = `${webhookId}${timestamp}${body}`;
```
| Content part | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------ |
| `webhookId` | The webhook's identifier received in the `X-ConfigCat-Webhook-ID` request header. |
| `timestamp` | The timestamp value received in the `X-ConfigCat-Webhook-Timestamp` request header. |
| `body` | The raw body of the received webhook request. If the webhook doesn't have a request body it can be left out. |
caution
The signature calculation is sensitive to any changes on the signed content, so it's important to not change the request body before the verification. Otherwise, the calculated signature could be completely different from the value received in the `X-ConfigCat-Webhook-Signature-V1` header.
##### Calculating signature[](#calculating-signature "Direct link to Calculating signature")
ConfigCat uses `HMAC` with `SHA-256` to sign webhooks. You can retrieve the **signing key(s)** required for the signature calculation from the [ConfigCat Dashboard's webhook page](https://app.configcat.com/product/webhooks).

info
For **key rotation** purposes, you can generate a secondary signing key. In this case ConfigCat sends two signatures (one signed with the *primary* and one signed with the *secondary* key) in the `X-ConfigCat-Webhook-Signature-V1` header separated by a comma (`,`):
```text
X-ConfigCat-Webhook-Signature-V1: RoO/UMvSRqzJ0OolMMuhHBbM8/Vjn+nTh+SKyLcQf0M=,heIrGPw6aylAZEX6xmSLrxIWVif5injeBCxWQ+0+b2U=
```
* Node.js
* Python
* Ruby
* PHP
* Go
* .NET
* Java
```js
const crypto = require('crypto');
// retrieved from the ConfigCat Dashboard
const signingKey =
'configcat_whsk_VN3juirnVh5pNvCKd81RYRYchxUX4j3NykbZG2fAy88=';
// retrieved from the the X-ConfigCat-Webhook-Signature-V1 request header
const receivedSignature = 'Ks3cYsu9Lslfo+hVxNC3oQWnsF9e5d73TI5t94D9DRA=';
// retrieved from the the X-ConfigCat-Webhook-ID request header
const requestId = 'b616ca659d154a5fb907dd8475792eeb';
// retrieved from the the X-ConfigCat-Webhook-Timestamp request header
const timestamp = 1669629035;
// the webhook request's raw body
const body = 'examplebody';
const contentToSign = `${requestId}${timestamp}${body}`;
const calculatedSignature = crypto
.createHmac('sha256', signingKey)
.update(contentToSign)
.digest('base64');
console.log(calculatedSignature == receivedSignature); // must be true
```
```python
import hmac
import base64
# retrieved from the ConfigCat Dashboard
signing_key = "configcat_whsk_VN3juirnVh5pNvCKd81RYRYchxUX4j3NykbZG2fAy88="
# retrieved from the X-ConfigCat-Webhook-Signature-V1 request header
received_signature = "Ks3cYsu9Lslfo+hVxNC3oQWnsF9e5d73TI5t94D9DRA="
# retrieved from the X-ConfigCat-Webhook-ID request header
request_id = "b616ca659d154a5fb907dd8475792eeb"
# retrieved from the X-ConfigCat-Webhook-Timestamp request header
timestamp = 1669629035
# the webhook request's raw body
body = "examplebody"
content_to_sign = request_id+str(timestamp)+body
signing_key_bytes = bytes(signing_key, 'utf-8')
calculated_signature = base64.b64encode(hmac.new(signing_key_bytes, bytes(content_to_sign, 'utf-8'), 'sha256').digest())
print(calculated_signature.decode() == received_signature) # must be true
```
```ruby
require 'openssl'
require 'base64'
# retrieved from the ConfigCat Dashboard
signing_key = "configcat_whsk_VN3juirnVh5pNvCKd81RYRYchxUX4j3NykbZG2fAy88="
# retrieved from the X-ConfigCat-Webhook-Signature-V1 request header
received_signature = "Ks3cYsu9Lslfo+hVxNC3oQWnsF9e5d73TI5t94D9DRA="
# retrieved from the X-ConfigCat-Webhook-ID request header
request_id = "b616ca659d154a5fb907dd8475792eeb"
# retrieved from the X-ConfigCat-Webhook-Timestamp request header
timestamp = 1669629035
# the webhook request's raw body
body = "examplebody"
content_to_sign = "#{request_id}#{timestamp}#{body}"
calculated_signature = Base64.strict_encode64(OpenSSL::HMAC.digest("sha256", signing_key, content_to_sign))
puts calculated_signature == received_signature # must be true
```
```php
changed in ConfigCat: \n\n##ChangeDetailsSlack##"
}
```
#### Connecting to Microsoft Teams[](#connecting-to-microsoft-teams "Direct link to Connecting to Microsoft Teams")
A few steps to set up Microsoft Teams and get a message when a setting changes:
1. In Microsoft Teams, create an [Incoming Webhook](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook#create-incoming-webhook-1) and copy the **Webhook URL**.
2. In ConfigCat, go to the [Webhooks](https://app.configcat.com/webhook) screen, and click **+ ADD WEBHOOK**.
3. Paste Microsoft Teams' **Webhhok URL** to ConfigCat's **URL** field.
4. Select **POST** as the **HTTP METHOD**.
5. Add the following request body:
```text
{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
"themeColor": "0072C6",
"title": "##ConfigName## - ##EnvironmentName##",
"text": "##ChangeDetailsTeams##",
"potentialAction": [
{
"@type": "OpenUri",
"name": "Open Config in ConfigCat Dashboard",
"targets": [
{ "os": "default", "uri": "##URL##" }
]
}
]
}
```
---
### Predefined Variations vs Free‑Form Values
Copy page
ConfigCat supports two value-modes for feature flags: *free-form values* and *predefined variations*. This guide explains the differences between these approaches and helps you choose the right one for your use case.
#### Overview[](#overview "Direct link to Overview")
In ConfigCat, you can configure feature flags to operate in either of these modes:
* **Free-form values** - Allows arbitrary values for non-boolean feature flags. You can set served values of such flags to any value.
* **Predefined variations** - Constrains feature flag values to a set of variations specified beforehand. You can select served values from a dropdown.

#### Free-form values[](#free-form-values "Direct link to Free-form values")
Free-form values are the traditional, unrestrictive mode that lets you enter a feature flag's exact value each time you set it.

##### Characteristics[](#characteristics "Direct link to Characteristics")
* **Direct Input**: You type or input the value directly when setting up flag rules
* **Ad-hoc Definition**: Values are defined on-the-fly as needed
* **No Reusability**: Each value must be entered separately for each rule
* **Simple Setup**: Straightforward for basic use cases
* **Flexible**: Any valid value can be entered at any time
##### Use cases[](#use-cases "Direct link to Use cases")
Free-form values work well when you have simple, one-off configurations where feature flag values are unique and unlikely to be reused. They're ideal when you need quick setup without upfront planning, especially when working with primitive values like booleans or simple strings and numbers. This approach is also suitable when values change frequently or unpredictably.
#### Predefined variations[](#predefined-variations "Direct link to Predefined variations")
Predefined variations allow you to define a set of reusable values upfront when creating a feature flag. These variations can then be selected from a dropdown when setting up flag rules. Each variation consists of three fields:

##### Variation fields[](#variation-fields "Direct link to Variation fields")
| Field | Description |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Served value | **Required.** The actual value that feature flag evaluation will return in your application when this variation is selected. |
| Display name | Optional. A human-readable identifier for the variation displayed in the dropdown. If not provided, a string representation of the served value is displayed instead. |
| Hint | Optional. Additional context or description to explain when or why to use this variation. It will be visible as a tooltip. |
##### Characteristics[](#characteristics-1 "Direct link to Characteristics")
* **Defined at Creation**: Variations must be defined when creating the feature flag
* **Reusability**: Define once, use multiple times across flag rules
* **Consistency**: Ensures the same values are used throughout your configuration
* **Dropdown Selection**: Choose from predefined options instead of typing
##### Use cases[](#use-cases-1 "Direct link to Use cases")
Predefined variations are ideal when you have a standard set of values used across multiple rules, especially when consistency is critical for things like color schemes, API endpoints, or configuration objects. They work well when multiple team members need to understand what each value represents and you want to prevent typos or invalid values. This approach is particularly valuable when complex values like JSON objects need to be reused, when you need to provide guidance on when to use specific values, and when values are known upfront and relatively stable.
#### Converting between free-form values and predefined variations[](#converting-between-free-form-values-and-predefined-variations "Direct link to Converting between free-form values and predefined variations")
ConfigCat provides an easy way to convert feature flags between free-form values and predefined variations.
##### Converting to predefined variations[](#converting-to-predefined-variations "Direct link to Converting to predefined variations")
You can convert a feature flag to use predefined variations by clicking the **Convert to use variations** item in the kebab (3 dots) menu of the feature flag.
When you convert a feature flag from free-form values to predefined variations, ConfigCat automatically collects all currently used values from your existing flag rules. These collected values are presented as suggested variations, but you can modify their display names and hints, or even add new variations.
The conversion doesn't affect your applications deployed to production.
##### Converting to free-form values[](#converting-to-free-form-values "Direct link to Converting to free-form values")
You can convert a feature flag to use free-form values by clicking the **Convert to use free-form values** item in the kebab (3 dots) menu of the feature flag. (For boolean feature flags, the corresponding menu item is **Convert to use ON/OFF toggle**.)
When you convert a feature flag from predefined variations to free-form values, the actual values from variations are extracted and feature flag values are updated to use the values directly. Display names and hints are irreversibly deleted, leaving only the values.
The conversion doesn't affect your applications deployed to production.
#### Working with predefined variations[](#working-with-predefined-variations "Direct link to Working with predefined variations")
##### Creating a feature flag with predefined variations[](#creating-a-feature-flag-with-predefined-variations "Direct link to Creating a feature flag with predefined variations")
When creating a new feature flag, you can choose between free-form values and predefined variations.
##### Managing predefined variations[](#managing-predefined-variations "Direct link to Managing predefined variations")
You can add/remove/modify predefined variations for a feature flag by clicking the related button in any served value dropdowns or by clicking the **Manage predefined variations** item in the kebab (3 dots) menu of the feature flag.

You can create additional variations as needed at any time. However, you can only remove a predefined variation if it is not currently in use.
You can modify the display name and hint of predefined variations at any time, but you can only change the served value of a predefined variation if it is not currently in use.
#### Variation ID vs predefined variations[](#variation-id-vs-predefined-variations "Direct link to Variation ID vs predefined variations")
ConfigCat also has a feature called *Variation ID*, but this is different from predefined variations, as it is designed primarily for analytics and A/B testing integrations. It is a hashed identifier of the feature flag's served value.
However, since predefined variations require unique served values, there is an inherent connection between the two concepts: a Variation ID uniquely identifies a predefined variation.
Therefore, if you enable the Variation ID feature in your product's preferences as explained [here](https://configcat.com/docs/advanced/variation-id-for-analytics.md#how-to-access-variation-ids), the **Manage predefined variations** dialog will also display the Variation IDs corresponding to the variations.
tip
Learn more about Variation ID [here](https://configcat.com/docs/advanced/variation-id-for-analytics.md).
---
### Endpoints
Copy page
The Proxy accepts HTTP requests on the following endpoints.
#### CDN Proxy[](#cdn-proxy "Direct link to CDN Proxy")
The CDN proxy endpoint's purpose is to forward the underlying *config JSON* to other ConfigCat SDKs used by your application.
GETOPTIONS/configuration-files/{path}
This endpoint is mainly used by ConfigCat SDKs to retrieve all required data for feature flag evaluation.
**Route parameters**:
* `path`: It's set by the ConfigCat SDK configured to use the ConfigCat Proxy. It contains either an SDK key or an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The `config.json` file is downloaded successfully.
* 204: In response to an `OPTIONS` request.
* 304: The `config.json` file isn't modified based on the `Etag` sent in the `If-None-Match` header.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
##### SDK Usage[](#sdk-usage "Direct link to SDK Usage")
In order to let a ConfigCat SDK use the Proxy, you have to set the SDK's `baseUrl` parameter to point to the Proxy's host.
example.js
```js
import * as configcat from "@configcat/sdk";
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) it works with, you can use that identifier prefixed with `configcat-proxy/` as the SDK key at the ConfigCat SDK's initialization.
So, let's assume you set up the Proxy with an SDK key mapped to the `my_sdk` SDK identifier:
example.js
```js
import * as configcat from "@configcat/sdk";
const configCatClient = configcat.getClient(
"configcat-proxy/my_sdk", // SDK identifier prefixed with 'configcat-proxy/'
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
##### Supported SDK Versions[](#supported-sdk-versions "Direct link to Supported SDK Versions")
The following SDK versions are supported by the `>=v0.3.X` Proxy's CDN endpoint:
| SDK | Version |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| .NET | >= [v9.0.0](https://github.com/configcat/.net-sdk/releases/tag/v9.0.0) |
| Android (Java) | >= [v10.0.0](https://github.com/configcat/android-sdk/releases/tag/v10.0.0) |
| C++ | >= [v4.0.0](https://github.com/configcat/cpp-sdk/releases/tag/v4.0.0) |
| Dart (Flutter) | >= [v4.0.0](https://github.com/configcat/dart-sdk/releases/tag/4.0.0) |
| Elixir | >= [v4.0.0](https://github.com/configcat/elixir-sdk/releases/tag/v4.0.0) |
| Go | >= [v9.0.0](https://github.com/configcat/go-sdk/releases/tag/v9.0.0) |
| Java | >= [v9.0.0](https://github.com/configcat/java-sdk/releases/tag/v9.0.0) |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node) | >= [v1.0.0](https://github.com/configcat/js-unified-sdk/releases) |
| JS - Legacy | >= [v9.0.0](https://github.com/configcat/js-sdk/releases/tag/v9.0.0) |
| JS SSR - Legacy | >= [v8.0.0](https://github.com/configcat/js-ssr-sdk/releases/tag/v8.0.0) |
| Kotlin | >= [v3.0.0](https://github.com/configcat/kotlin-sdk/releases/tag/3.0.0) |
| Node - Legacy | >= [v11.0.0](https://github.com/configcat/node-sdk/releases/tag/v11.0.0) |
| PHP 8.1+ | >= [v9.0.0](https://github.com/configcat/php-sdk/releases/tag/v9.0.0) |
| PHP 7.1+ | >= [v3.0.0](https://github.com/configcat/php7-sdk/releases/tag/v3.0.0) |
| Python | >= [v9.0.3](https://github.com/configcat/python-sdk/releases/tag/v9.0.3) |
| React | >= [v4.0.0](https://github.com/configcat/react-sdk/releases/tag/v4.0.0) |
| Ruby | >= [v8.0.0](https://github.com/configcat/ruby-sdk/releases/tag/v8.0.0) |
| Rust | >= [v0.1.0](https://github.com/configcat/rust-sdk/releases/tag/v0.1.0) |
| Swift (iOS) | >= [v11.0.0](https://github.com/configcat/swift-sdk/releases/tag/11.0.0) |
##### Available Options[](#available-options "Direct link to Available Options")
The following CDN Proxy related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable\`\`\`yaml
http:
cdn\_proxy:
enabled: \
```````shell
CONFIGCAT_HTTP_CDN_PROXY_ENABLED=
``` | `true` | Turns the hosting of the CDN proxy endpoint on/off. This endpoint can be used by other ConfigCat SDKs in your applications. |
| - YAML - Environment variable```yaml
http:
cdn_proxy:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML - Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`. When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML - Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin. When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value. The `if_no_match` option is mandatory if this option is used. When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML - Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML - Environment variable```yaml
http:
cdn_proxy:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_CDN_PROXY_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each CDN proxy endpoint response. |
## API[](#api "Direct link to API")
These API endpoints are for server side feature flag evaluation.
### Endpoints using SDK key[](#endpoints-using-sdk-key "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `X-ConfigCat-SdkKey` HTTP header.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
POSTOPTIONS/api/eval
This endpoint evaluates a single feature flag identified by a `key` with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines the feature flag's config / environment.
**Request body**:
```json
{
"key": "",
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header or the `key` from the request body is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/eval"; // Proxy API URL
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"X-ConfigCat-SdkKey": "#YOUR-SDK-KEY#",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/eval-all
This endpoint evaluates all feature flags with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/eval-all"; // Proxy API URL
const data = {
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"X-ConfigCat-SdkKey": "#YOUR-SDK-KEY#",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/refresh
This endpoint commands the underlying SDK to download the latest available *config JSON*.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that identifies an SDK within the Proxy.
**Responses**:
* 200: The refresh was successful.
* 204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
GETOPTIONS/api/keys
This endpoint returns all feature flag keys belonging to the given SDK key.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that identifies an SDK within the Proxy.
**Responses**:
* 200: The keys are returned successfully.
* Response body:
```json
{
"keys": [
"feature-flag-key-1",
"feature-flag-key-2"
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier "Direct link to Endpoints using SDK identifier")
The following endpoints are using an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) to determine which config / environment is the target of the desired action. The SDK identifier must be provided as a route parameter of the HTTP request.
POSTOPTIONS/api/{sdkId}/eval
This endpoint evaluates a single feature flag identified by a `key` with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines the feature flag's config / environment.
**Request body**:
```json
{
"key": "",
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` or the `key` from the request body is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/#SDK-IDENTIFIER#/eval"; // Proxy API URL with SDK identifier
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/{sdkId}/eval-all
This endpoint evaluates all feature flags with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/#SDK-IDENTIFIER#/eval-all"; // Proxy API URL with SDK identifier
const data = {
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/{sdkId}/refresh
This endpoint commands the underlying SDK to download the latest available *config JSON*.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The refresh was successful.
* 204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
GETOPTIONS/api/{sdkId}/keys
This endpoint returns all feature flag keys belonging to the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The keys are returned successfully.
* Response body:
```json
{
"keys": [
"feature-flag-key-1",
"feature-flag-key-2"
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
### Available Options[](#available-options-1 "Direct link to Available Options")
The following API related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable```yaml
http:
api:
enabled:
``````shell
CONFIGCAT_HTTP_API_ENABLED=
``` | `true` | Turns the hosting of the API endpoints on/off. These endpoints can be used for server side feature flag evaluation. |
| - YAML - Environment variable```yaml
http:
api:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_API_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML - Environment variable```yaml
http:
api:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`. When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML - Environment variable```yaml
http:
api:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin. When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value. The `if_no_match` option is mandatory if this option is used. When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML - Environment variable```yaml
http:
api:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML - Environment variable```yaml
http:
api:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_API_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each API endpoint response. |
| - YAML - Environment variable```yaml
http:
api:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_API_AUTH_HEADERS='{"X-API-KEY":""}'
``` | - | Additional headers that must be on each request sent to the API endpoints. If the request doesn't include the specified header, or the values are not matching, the Proxy will respond with a `401` HTTP status code. |
## OpenFeature Remote Evaluation Protocol (OFREP)[](#openfeature-remote-evaluation-protocol-ofrep "Direct link to OpenFeature Remote Evaluation Protocol (OFREP)")
info
OFREP compatibility is only available from Proxy version [`v2.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0).
The Proxy conforms to the [OpenFeature Remote Evaluation Protocol](https://github.com/open-feature/protocol), which means it can be used with OFREP compatible OpenFeature providers.
### Endpoints using SDK key[](#endpoints-using-sdk-key-1 "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `X-ConfigCat-SdkKey` HTTP header.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
POSTOPTIONS/ofrep/v1/evaluate/flags/{key}
This endpoint is used by OFREP compatible OpenFeature providers to evaluate a feature flag.
**Route parameters**:
* `key`: The key of the feature flag to evaluate.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines the feature flag's config / environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK or the feature flag for `key` is not found.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkKey", "#YOUR-SDK-KEY#"],
],
}),
);
```
POSTOPTIONS/ofrep/v1/evaluate/flags
This endpoint is used by OFREP compatible OpenFeature providers to evaluate all feature flags.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"flags": [
{
"key": "",
"value": ,
"variant": "",
"reason": ""
},
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkKey", "#YOUR-SDK-KEY#"],
],
}),
);
```
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier-1 "Direct link to Endpoints using SDK identifier")
The following endpoints are using an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) to determine which config / environment is the target of the desired action. The SDK identifier must be provided in the `X-ConfigCat-SdkId` HTTP header.
POSTOPTIONS/ofrep/v1/evaluate/flags/{key}
This endpoint is used by OFREP compatible OpenFeature providers to evaluate a feature flag.
**Route parameters**:
* `key`: The key of the feature flag to evaluate.
**Headers**:
* `X-ConfigCat-SdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines the feature flag's config / environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkId` header is missing.
* 404: The `X-ConfigCat-SdkId` header is pointing to a non-existent SDK or the feature flag for `key` is not found.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkId", "#SDK-IDENTIFIER#"],
],
}),
);
```
POSTOPTIONS/ofrep/v1/evaluate/flags
This endpoint is used by OFREP compatible OpenFeature providers to evaluate all feature flags.
**Headers**:
* `X-ConfigCat-SdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"flags": [
{
"key": "",
"value": ,
"variant": "",
"reason": ""
},
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkId` header is missing.
* 404: The `X-ConfigCat-SdkId` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: 'http://localhost:8050', // Proxy URL
headers: [
["X-ConfigCat-SdkId", "#SDK-IDENTIFIER#"],
],
}),
);
```
### Available Options[](#available-options-2 "Direct link to Available Options")
The following OFREP related options are available:
| Option | Default | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable```yaml
http:
ofrep:
enabled:
``````shell
CONFIGCAT_HTTP_OFREP_ENABLED=
``` | `true` | Turns the hosting of the OFREP endpoints on/off. These endpoints can be used by OFREP compatible OpenFeature providers for server side feature flag evaluation. |
| - YAML - Environment variable```yaml
http:
ofrep:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML - Environment variable```yaml
http:
ofrep:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`. When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML - Environment variable```yaml
http:
ofrep:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin. When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value. The `if_no_match` option is mandatory if this option is used. When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML - Environment variable```yaml
http:
ofrep:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML - Environment variable```yaml
http:
ofrep:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_OFREP_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each OFREP endpoint response. |
| - YAML - Environment variable```yaml
http:
ofrep:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_OFREP_AUTH_HEADERS='{"X-API-KEY":""}'
``` | - | Additional headers that must be on each request sent to the OFREP endpoints. If the request doesn't include the specified header, or the values are not matching, the Proxy will respond with a `401` HTTP status code. |
## SSE[](#sse "Direct link to SSE")
The SSE endpoint allows you to subscribe for feature flag value changes through [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) connections.
### Endpoints using SDK key[](#endpoints-using-sdk-key-2 "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `sdkKey` field of the base64 encoded `data` route parameter.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
GETOPTIONS/sse/eval/k/{data}
This endpoint subscribes to a single flag's changes. Whenever the watched flag's value changes, the Proxy sends the new value to each connected client.
**Route parameters**:
* `data`: The `base64` encoded input data for feature flag evaluation that must contain the SDK key, the feature flag's key, and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `data`, or the `sdkKey` or `key` field of `data` is missing.
* 404: The `sdkKey` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
sdkKey: "#YOUR-SDK-KEY#",
key: "isMyAwesomeFeatureEnabled",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/eval/k/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
GETOPTIONS/sse/eval-all/k/{data}
This endpoint subscribes to all feature flags' changes behind the given SDK key. When any of the watched flags' value change, the Proxy sends its new value to each connected client.
**Route parameters**:
* `data`: The `base64` encoded input data for feature flag evaluation that contains the SDK key and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkKey` field of `data` is missing.
* 404: The `sdkKey` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
sdkKey: "#YOUR-SDK-KEY#",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/eval-all/k/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"feature-flag-key":{"value":,"variationId":""}}
};
```
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier-2 "Direct link to Endpoints using SDK identifier")
The following endpoints are using an SDK identifier to determine which config / environment is the target of the desired action. The SDK identifier must be provided in the `sdkId` route parameter.
GETOPTIONS/sse/{sdkId}/eval/{data}
This endpoint subscribes to a single flag's changes. Whenever the watched flag's value changes, the Proxy sends the new value to each connected client.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
* `data`: The `base64` encoded input data for feature flag evaluation that must contain the feature flag's key and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId`, `data`, or the `key` attribute of `data` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
key: "isMyAwesomeFeatureEnabled",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/#SDK-IDENTIFIER#/eval/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
GETOPTIONS/sse/{sdkId}/eval-all/{data}
This endpoint subscribes to all feature flags' changes behind the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key). When any of the watched flags' value change, the Proxy sends its new value to each connected client.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
* `data`: **Optional**. The `base64` encoded input data for feature flag evaluation that contains a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/#SDK-IDENTIFIER#/eval-all/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"feature-flag-key":{"value":,"variationId":""}}
};
```
### Available Options[](#available-options-3 "Direct link to Available Options")
The following SSE related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable```yaml
http:
sse:
enabled:
``````shell
CONFIGCAT_HTTP_SSE_ENABLED=
``` | `true` | Turns the hosting of the SSE endpoint on/off, This endpoint can be used to stream feature flag value changes. |
| - YAML - Environment variable```yaml
http:
sse:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_SSE_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML - Environment variable```yaml
http:
sse:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`. When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML - Environment variable```yaml
http:
sse:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin. When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value. The `if_no_match` option is mandatory if this option is used. When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML - Environment variable```yaml
http:
sse:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML - Environment variable```yaml
http:
sse:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_SSE_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each [SSE endpoint](#sse) response. |
| - YAML - Environment variable```yaml
http:
sse:
log:
level: ""
``````shell
CONFIGCAT_HTTP_SSE_LOG_LEVEL=""
``` | `warn` | The verbosity of the SSE related logs. Possible values: `error`, `warn`, `info` or `debug`. |
## Webhook[](#webhook "Direct link to Webhook")
Through the webhook endpoint, you can notify the Proxy about the availability of new feature flag evaluation data. Also, with the appropriate [SDK options](https://configcat.com/docs/advanced/proxy/proxy-overview.md#additional-options-for-underlying-sdks), the Proxy can [validate the signature](https://configcat.com/docs/advanced/notifications-webhooks.md#verifying-webhook-requests) of each incoming webhook request.
info
If you use the [automatic configuration with Proxy profiles](https://configcat.com/docs/advanced/proxy/proxy-overview.md#1-automatic-configuration-with-proxy-profiles), you don't have to set up individual webhooks manually. You can follow the documentation of webhook notifications for Proxy profiles [here](https://configcat.com/docs/advanced/proxy/proxy-overview.md#webhook-notification).
GETPOST/hook/{sdkId}
Notifies the Proxy that the SDK with the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) must refresh its *config JSON* to the latest version.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The Proxy accepted the notification.
* 400: The `sdkId` is missing or the [webhook signature validation](https://configcat.com/docs/advanced/notifications-webhooks.md#verifying-webhook-requests) failed.
* 404: The `sdkId` is pointing to a non-existent SDK.
### ConfigCat Dashboard[](#configcat-dashboard "Direct link to ConfigCat Dashboard")
You can set up webhooks to invoke the Proxy on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard.

### Available Options[](#available-options-4 "Direct link to Available Options")
The following webhook related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable```yaml
http:
webhook:
enabled:
``````shell
CONFIGCAT_HTTP_WEBHOOK_ENABLED=
``` | `true` | Turns the hosting of the Webhook endpoint on/off. This endpoint can be used to notify the Proxy about the availability of new feature flag evaluation data. |
| - YAML - Environment variable```yaml
http:
webhook:
auth:
user: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_USER=""
``` | - | Basic authentication user. The basic authentication webhook header can be set on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard. |
| - YAML - Environment variable```yaml
http:
webhook:
auth:
password: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_PASSWORD=""
``` | - | Basic authentication password. The basic authentication webhook header can be set on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard. |
| - YAML - Environment variable```yaml
http:
webhook:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_HEADERS='{"X-API-KEY":""}'
``` | - | Additional headers that ConfigCat must send with each request to the Webhook endpoint. Webhook headers can be set on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard. |
```````
---
### gRPC
Copy page
The ConfigCat Proxy can communicate over [gRPC](https://grpc.io), an open-source, high-performance RPC framework with client support in several languages.
To establish gRPC connections, you'll need the protobuf and the gRPC [service definition](https://github.com/configcat/configcat-proxy/blob/main/grpc/proto/flag_service.proto). It's required to generate clients with [`protoc`](https://protobuf.dev/downloads/) for your [desired platform](https://protobuf.dev/reference/).
flag\_service.proto
```protobuf
syntax = "proto3";
option go_package = "github.com/configcat/configcat-proxy/grpc/proto";
package configcat;
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
// Service that contains feature flag evaluation procedures.
service FlagService {
// Stream for getting notified when a feature flag's value changes.
rpc EvalFlagStream(EvalRequest) returns (stream EvalResponse) {}
// Stream for getting notified when any feature flag's value changes.
rpc EvalAllFlagsStream(EvalRequest) returns (stream EvalAllResponse) {}
// Evaluates a feature flag.
rpc EvalFlag(EvalRequest) returns (EvalResponse) {}
// Evaluates each feature flag.
rpc EvalAllFlags(EvalRequest) returns (EvalAllResponse) {}
// Requests the keys of each feature flag.
rpc GetKeys(KeysRequest) returns (KeysResponse) {}
// Commands the underlying SDK to refresh its evaluation data.
rpc Refresh(RefreshRequest) returns (google.protobuf.Empty) {}
}
// Feature flag evaluation request message.
message EvalRequest {
// The SDK identifier. Deprecated, the field `target` should be used instead for SDK identification.
string sdk_id = 1 [ deprecated = true ];
// The feature flag's key to evaluate.
string key = 2;
// The user object.
map user = 3;
// The evaluation request's target.
Target target = 4;
}
// Feature flag evaluation response message.
message EvalResponse {
// The evaluated value.
oneof value {
int32 int_value = 1;
double double_value = 2;
string string_value = 3;
bool bool_value = 4;
}
// The variation ID.
string variation_id = 5;
}
// Response message that contains the evaluation result of each feature flag.
message EvalAllResponse {
// The evaluated value of each feature flag.
map values = 1;
}
// Request message for getting each available feature flag's key.
message KeysRequest {
// The SDK identifier. Deprecated, the field `target` should be used instead for SDK identification.
string sdk_id = 1 [ deprecated = true ];
// The request's target.
Target target = 2;
}
// Response message that contains each available feature flag's key.
message KeysResponse {
// The keys of each feature flag.
repeated string keys = 1;
}
// Request message for the given SDK to refresh its evaluation data.
message RefreshRequest {
// The SDK identifier. Deprecated, the field `target` should be used instead for SDK identification.
string sdk_id = 1 [ deprecated = true ];
// The request's target.
Target target = 2;
}
// Defines the possible values that can be set in the `user` map.
message UserValue {
oneof value {
double number_value = 1;
string string_value = 2;
google.protobuf.Timestamp time_value = 3;
StringList string_list_value = 4;
}
}
// Identifies the target of evaluation requests by either an SDK Id or an SDK Key.
message Target {
oneof identifier {
// The SDK Id.
string sdk_id = 1;
// The SDK key.
string sdk_key = 2;
}
}
// Represents a list of strings.
message StringList {
repeated string values = 1;
}
```
info
In order to secure the gRPC communication with the Proxy, set up [TLS](https://configcat.com/docs/advanced/proxy/proxy-overview.md#tls).
#### Client Usage[](#client-usage "Direct link to Client Usage")
The following example uses a generated Go client, but gRPC clients generated for other languages are working as well.
example.go
```go
conn, err := grpc.NewClient("localhost:50051",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
// Any TLS options
})))
if err != nil {
panic(err)
}
defer func() {
_ = conn.Close()
}()
client := proto.NewFlagServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err := client.EvalFlag(ctx, &proto.EvalRequest{
Target: &proto.Target{Identifier: &proto.Target_SdkKey{SdkKey: "#YOUR-SDK-KEY#"}},
// Or with SDK identifier
// Target: &proto.Target{Identifier: &proto.Target_SdkId{SdkId: "#SDK-IDENTIFIER#"}},
Key: "",
User: map[string]*proto.UserValue{"Identifier": {Value: &proto.UserValue_StringValue{StringValue: ""}}},
})
if err != nil {
panic(err)
}
fmt.Printf("Evaluation result: %v", resp.GetBoolValue())
```
#### Health Check[](#health-check "Direct link to Health Check")
The Proxy exposes health information over a [standardized health RPC service](https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto).
Clients can set `""` as the `service` parameter (or skip specifying it) to get the health status of the gRPC server. Exposing the health check service is configurable and turned on by default.
For more details about gRPC health checking, check out the [official documentation](https://grpc.io/docs/guides/health-checking/).
#### Server Reflection[](#server-reflection "Direct link to Server Reflection")
The Proxy can expose its protobuf-defined feature flag evaluation API over a [standardized reflection RPC service](https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto), including all types referenced by the request and response messages. Exposing the reflection service is configurable and turned off by default.
For more details about gRPC server reflection, check out the [official documentation](https://grpc.io/docs/guides/reflection/).
#### Available Options[](#available-options "Direct link to Available Options")
The following gRPC related options are available:
* YAML
* Environment variables
options.yml
```yaml
grpc:
enabled:
port: 50051
server_reflection_enabled:
health_check_enabled:
keep_alive:
max_connection_idle: 15
max_connection_age: 30
max_connection_age_grace: 5
time: 5
timeout: 1
log:
level: ""
```
```shell
CONFIGCAT_GRPC_ENABLED=
CONFIGCAT_GRPC_PORT=50051
CONFIGCAT_GRPC_HEALTH_CHECK_ENABLED=
CONFIGCAT_GRPC_SERVER_REFLECTION_ENABLED=
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_IDLE=15
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_AGE=30
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_AGE_GRACE=5
CONFIGCAT_GRPC_KEEP_ALIVE_TIME=5
CONFIGCAT_GRPC_KEEP_ALIVE_TIMEOUT=1
CONFIGCAT_GRPC_LOG_LEVEL=""
```
Here's the explanation for each option:
| Option | Default | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable\`\`\`yaml
grpc:
enabled: \
```````shell
CONFIGCAT_GRPC_ENABLED=
``` | `true` | Turns the ability to communicate with the Proxy through gRPC on/off. |
| - YAML - Environment variable```yaml
grpc:
port: 50051
``````shell
CONFIGCAT_GRPC_PORT=50051
``` | `50051` | The port used for gRPC communication. |
| - YAML - Environment variable```yaml
grpc:
health_check_enabled:
``````shell
CONFIGCAT_GRPC_HEALTH_CHECK_ENABLED=
``` | `true` | Turns the [gRPC health check service](https://grpc.io/docs/guides/health-checking/) on/off. |
| - YAML - Environment variable```yaml
grpc:
server_reflection_enabled:
``````shell
CONFIGCAT_GRPC_SERVER_REFLECTION_ENABLED=
``` | `false` | Turns the [gRPC server reflection](https://grpc.io/docs/guides/reflection/) on/off. |
| - YAML - Environment variable```yaml
grpc:
keep_alive:
max_connection_idle: 15
``````shell
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_IDLE=15
``` | `INT_MAX (Infinite)` | Maximum time in seconds that a channel may have no outstanding rpcs, after which the server will close the connection. [More about the gRPC keep-alive](https://grpc.io/docs/guides/keepalive/). |
| - YAML - Environment variable```yaml
grpc:
keep_alive:
max_connection_age: 30
``````shell
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_AGE=30
``` | `INT_MAX (Infinite)` | Maximum time in seconds that a channel may exist. [More about the gRPC keep-alive](https://grpc.io/docs/guides/keepalive/). |
| - YAML - Environment variable```yaml
grpc:
keep_alive:
max_connection_age_grace: 5
``````shell
CONFIGCAT_GRPC_KEEP_ALIVE_MAX_CONNECTION_AGE_GRACE=5
``` | `INT_MAX (Infinite)` | Grace period in seconds after the channel reaches its max age. [More about the gRPC keep-alive](https://grpc.io/docs/guides/keepalive/). |
| - YAML - Environment variable```yaml
grpc:
keep_alive:
time: 5
``````shell
CONFIGCAT_GRPC_KEEP_ALIVE_TIME=5
``` | `7200` | The interval in seconds between PING frames. [More about the gRPC keep-alive](https://grpc.io/docs/guides/keepalive/). |
| - YAML - Environment variable```yaml
grpc:
keep_alive:
timeout: 1
``````shell
CONFIGCAT_GRPC_KEEP_ALIVE_TIMEOUT=1
``` | `20` | The timeout in seconds for a PING frame to be acknowledged. If sender does not receive an acknowledgment within this time, it will close the connection. [More about the gRPC keep-alive](https://grpc.io/docs/guides/keepalive/). |
| - YAML - Environment variable```yaml
grpc:
log:
level: ""
``````shell
CONFIGCAT_GRPC_LOG_LEVEL=""
``` | `warn` | The verbosity of the gRPC related logs. Possible values: `error`, `warn`, `info` or `debug`. When `debug` is set, the Proxy will log each RPC with additional details. |
```````
---
### Monitoring
Copy page
The ConfigCat Proxy provides diagnostic data including health status, metrics, and traces.
info
Exposed endpoints (`/status` and `/metrics`) are served on a specific port, so you can separate them from the public HTTP communication.
These are the basic diagnostic-related options:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------- |
| - YAML - Environment variable\`\`\`yaml
diag:
enabled: \
```````shell
CONFIGCAT_DIAG_ENABLED=
``` | `true` | Turns the collection of diagnostic data on/off. |
| - YAML - Environment variable```yaml
diag:
port: 8051
``````shell
CONFIGCAT_DIAG_PORT=8051
``` | `8051` | The port used by the diagnostics HTTP server. |
## Status Endpoint[](#status "Direct link to Status Endpoint")
The Proxy provides status information (health check) about its components on the following endpoint:
GETOPTIONS/status
The Proxy regularly checks whether the underlying SDKs can communicate with their configured source and with the cache. This endpoint returns the actual state of these checks.
**Responses**:
* 200: The status returned successfully.
* 204: In response to an `OPTIONS` request.
**Example Response**:
```json
{
"status": "healthy",
"sdks": {
"my_sdk": {
"key": "****************************************hwTYg",
"mode": "online",
"source": {
"type": "remote",
"status": "healthy",
"records": [
"Mon, 29 May 2023 16:36:40 UTC: [ok] config fetched"
]
}
},
"another_sdk": {
"key": "****************************************ovVnQ",
"mode": "offline",
"source": {
"type": "cache",
"status": "healthy",
"records": [
"Mon, 29 May 2023 16:36:40 UTC: [ok] reload from cache succeeded",
"Mon, 29 May 2023 16:36:45 UTC: [ok] config from cache not modified"
]
}
}
},
"cache": {
"status": "healthy",
"records": [
"Mon, 29 May 2023 16:36:40 UTC: [ok] cache read succeeded",
"Mon, 29 May 2023 16:36:40 UTC: [ok] cache write succeeded",
"Mon, 29 May 2023 16:36:40 UTC: [ok] cache read succeeded",
"Mon, 29 May 2023 16:36:45 UTC: [ok] cache read succeeded"
]
}
}
```
**Details**:
If everything is operational, each `status` node shows the value `healthy`. If a component encounters a failure, it'll put an error to its `records` collection. If a component's last two records are errors, its `status` will switch to `degraded`. If a component becomes operational again it'll put an `[ok]` to the `records` and will switch back to `healthy`.
If an SDK couldn't initialize itself neither from an external cache nor from the ConfigCat CDN, its status will be `down`. It means, this SDK is not able to accept evaluation requests because it doesn't have a valid *config JSON* to work with.
If an SDK was able to initialize from its configured source, but its last two attempts to refresh has been failed (either from cache or from the ConfigCat CDN), it will become `degraded` because each refresh attempt will put an error to its `records` collection. This means, it's still able to evaluate feature flags, but it might work on a stale *config JSON*.
The root `status` is `healthy` if all of the SDKs are `healthy`. If any of the SDKs become `degraded` or `down`, the root will also switch to `degraded` (or `down` if each SDK is `down`).
You can control whether metrics collection should be enabled with the following configuration option:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------ |
| - YAML - Environment variable```yaml
diag:
status:
enabled:
``````shell
CONFIGCAT_DIAG_STATUS_ENABLED=
``` | `true` | Turns the hosting of the [status endpoint](#status) on the diagnostics HTTP server on/off. |
info
You can enable the status endpoint on the main HTTP port (default: `8050`) with the [HTTP configuration options](https://configcat.com/docs/advanced/proxy/proxy-overview.md#http).
## Metrics[](#metrics "Direct link to Metrics")
If enabled, the Proxy collects various metrics. These can be either exported in Prometheus format or sent to an OTLP-compatible observability backend.
You can control whether metric collection should be enabled with the following configuration option:
| Option | Default | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------ | ------- | -------------------------------- |
| - YAML - Environment variable```yaml
diag:
metrics:
enabled:
``````shell
CONFIGCAT_DIAG_METRICS_ENABLED=
``` | `true` | Turns metrics collection on/off. |
### Prometheus[](#prometheus-metrics "Direct link to Prometheus")
You can set up the Proxy to export metrics about its internal state in Prometheus format. These metrics are served on the `/metrics` endpoint.
#### Custom Metrics[](#custom-metrics "Direct link to Custom Metrics")
| Name | Type | Description |
| --------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `configcat_stream_connections` | Gauge | Number of active client connections per stream.
Tags:- `sdk`: The SDK's identifier that handles the connection. - `type`: `sse` or `grpc`. - `flag`: The streamed feature flag's key. |
| `configcat_stream_msg_sent_total` | Counter | Total number of all messages sent with streaming.
Tags:- `sdk`: The related SDK's identifier. - `type`: `sse` or `grpc`. - `flag`: The evaluated feature flag's key. |
The Proxy also exports metrics about the Go environment, e.g., `go_goroutines` or `go_memstats_alloc_bytes`, and process-related stats, e.g., `process_cpu_seconds_total`.
#### Integration[](#integration "Direct link to Integration")
To integrate with Prometheus, put the following scrape config—that points to the Proxy—into your Prometheus configuration:
```yaml
scrape_configs:
- job_name: configcat_proxy
metrics_path: /metrics
static_configs:
- targets:
- :8051
```
#### Configuration Options[](#configuration-options "Direct link to Configuration Options")
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------ |
| - YAML - Environment variable```yaml
diag:
metrics:
prometheus:
enabled:
``````shell
CONFIGCAT_DIAG_METRICS_PROMETHEUS_ENABLED=
``` | `true` | Turns the Prometheus compatible `/metrics` endpoint on the diagnostics HTTP server on/off. |
### OTLP[](#otlp "Direct link to OTLP")
You can set up the Proxy to send metrics via [OTLP](https://opentelemetry.io/docs/specs/otlp/) to a compatible collector such as [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-OTLPEndpoint.html), [NewRelic](https://docs.newrelic.com/docs/opentelemetry/get-started/apm-monitoring/opentelemetry-apm-intro/), [DataDog](https://docs.datadoghq.com/opentelemetry/setup/otlp_ingest_in_the_agent), or [Honeycomb](https://docs.honeycomb.io/send-data/opentelemetry/).
#### Custom Metrics[](#custom-metrics-1 "Direct link to Custom Metrics")
| Name | Type | Description |
| ----------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `stream.connections` | Gauge | Number of active client connections per stream.
Tags:- `sdk`: The SDK's identifier that handles the connection. - `type`: `sse` or `grpc`. - `flag`: The streamed feature flag's key. |
| `stream.msg.sent.total` | Counter | Total number of all messages sent with streaming.
Tags:- `sdk`: The related SDK's identifier. - `type`: `sse` or `grpc`. - `flag`: The evaluated feature flag's key. |
#### Configuration Options[](#configuration-options-1 "Direct link to Configuration Options")
| Option | Default | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------ |
| - YAML - Environment variable```yaml
diag:
metrics:
otlp:
enabled:
``````shell
CONFIGCAT_DIAG_METRICS_OTLP_ENABLED=
``` | `false` | Turns the sending of metrics via OTLP on/off. |
| - YAML - Environment variable```yaml
diag:
metrics:
otlp:
protocol: ""
``````shell
CONFIGCAT_DIAG_METRICS_OTLP_PROTOCOL=""
``` | `http` | The protocol used to send metrics over OTLP. Possible values: `http`, `https`, and `grpc`. |
| - YAML - Environment variable```yaml
diag:
metrics:
otlp:
endpoint: "localhost:4318"
``````shell
CONFIGCAT_DIAG_METRICS_OTLP_ENDPOINT="localhost:4318"
``` | `localhost:4318` | The OTLP collector's endpoint. |
Additional OTLP-related options can be set by using the default [OpenTelemetry environment variables](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/). For example, to set custom headers for each OTLP request, you can use the `OTEL_EXPORTER_OTLP_HEADERS` environment variable.
```shell
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer "
```
## Traces[](#traces "Direct link to Traces")
The Proxy is able to send traces via [OTLP](https://opentelemetry.io/docs/specs/otlp/) to a compatible collector such as [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-OTLPEndpoint.html), [NewRelic](https://docs.newrelic.com/docs/opentelemetry/get-started/apm-monitoring/opentelemetry-apm-intro/), [DataDog](https://docs.datadoghq.com/opentelemetry/setup/otlp_ingest_in_the_agent), or [Honeycomb](https://docs.honeycomb.io/send-data/opentelemetry/).
You can control whether trace collection should be enabled with the following configuration option:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------ |
| - YAML - Environment variable```yaml
diag:
traces:
enabled:
``````shell
CONFIGCAT_DIAG_TRACES_ENABLED=
``` | `false` | Turns trace collection on/off. |
#### OTLP-related Options[](#otlp-related-options "Direct link to OTLP-related Options")
| Option | Default | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | ----------------------------------------------------------------------------------------- |
| - YAML - Environment variable```yaml
diag:
traces:
otlp:
enabled:
``````shell
CONFIGCAT_DIAG_TRACES_OTLP_ENABLED=
``` | `false` | Turns the sending of traces via OTLP on/off. |
| - YAML - Environment variable```yaml
diag:
traces:
otlp:
protocol: ""
``````shell
CONFIGCAT_DIAG_TRACES_OTLP_PROTOCOL=""
``` | `http` | The protocol used to send traces over OTLP. Possible values: `http`, `https`, and `grpc`. |
| - YAML - Environment variable```yaml
diag:
traces:
otlp:
endpoint: "localhost:4318"
``````shell
CONFIGCAT_DIAG_TRACES_OTLP_ENDPOINT="localhost:4318"
``` | `localhost:4318` | The OTLP collector's endpoint. |
Additional OTLP-related options can be set by using the default [OpenTelemetry environment variables](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/). For example, to set custom headers for each OTLP request, you can use the `OTEL_EXPORTER_OTLP_HEADERS` environment variable.
```shell
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer "
```
## OpenTelemetry Instrumentation Libraries[](#opentelemetry-instrumentation-libraries "Direct link to OpenTelemetry Instrumentation Libraries")
Metrics and traces are also exported by the following official OpenTelemetry instrumentation libraries:
* [otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/net/http/otelhttp)
* [otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/google.golang.org/grpc/otelgrpc)
* [redisotel](https://github.com/redis/go-redis/tree/master/extra/redisotel)
* [otelmongo](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo)
* [otelaws](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws)
```````
---
### ConfigCat Proxy
Copy page
The [ConfigCat Proxy](https://github.com/configcat/configcat-proxy) allows you to host a feature flag evaluation service in your own infrastructure. It's a small Go application that communicates with ConfigCat's CDN network and caches/proxies *config JSON* files for your frontend and backend applications. The *config JSON* contains all the data that is needed for ConfigCat SDKs to evaluate feature flags.
The Proxy provides the following:
* **Performance**: The Proxy can be deployed close to your applications and can serve the downloaded *config JSON* files from memory. ConfigCat SDKs then can operate on the [proxied *config JSON*](https://configcat.com/docs/advanced/proxy/endpoints.md#cdn-proxy). This can reduce the duration of feature flag evaluation for stateless or short lived applications.
* **Reliability**: The Proxy can store the downloaded *config JSON* files in an external [cache](#cache). It can fall back to operating on the cached *config JSON* if the ConfigCat CDN network becomes inaccessible.
* **Security**: The Proxy can act as a [server side flag evaluation](https://configcat.com/docs/advanced/proxy/endpoints.md#api) component. Using it like that can prevent the exposure of *config JSON* files to frontend and mobile applications.
* **Scalability**: Horizontal scaling allows you to align with the load coming from your applications accordingly.
* **Streaming**: The Proxy provides real-time feature flag change notifications via [Server-Sent Events (SSE)](https://configcat.com/docs/advanced/proxy/endpoints.md#sse) and [gRPC](https://configcat.com/docs/advanced/proxy/grpc.md).
#### Architecture[](#architecture "Direct link to Architecture")
The following diagram shows the high level architecture of the Proxy.

##### How It Works[](#how-it-works "Direct link to How It Works")
The Proxy wraps one or more SDK instances for handling feature flag evaluation requests. It also serves the related *config JSON* files that can be consumed by other ConfigCat SDKs running in your applications.
Within the Proxy, the underlying SDK instances can run in the following modes:
* **Online**: In this mode, the underlying SDK has an active connection to the ConfigCat CDN network through the internet.
* **Offline**: In [this mode](#offline-mode), the underlying SDK doesn't have an active connection to ConfigCat. Instead, it uses the configured cache or a file as a source of its *config JSON*.
With the combination of the above modes, you can construct a cluster of proxies where only one node is responsible for the communication with ConfigCat, and all the other nodes are working from a central cache.

##### Communication[](#communication "Direct link to Communication")
There are three ways how the Proxy is informed about the availability of new feature flag evaluation data:
* **Polling**: The ConfigCat SDKs within the Proxy are regularly polling the ConfigCat CDN for new *config JSON* versions.
* **Webhook**: The Proxy has [webhook endpoints](https://configcat.com/docs/advanced/proxy/endpoints.md#webhook) (for each underlying SDK) which can be set on the [ConfigCat Dashboard](https://app.configcat.com/product/webhooks) to be invoked when someone saves & publishes new feature flag changes.
* **Cache polling / file watching**: In [offline mode](#offline-mode), the Proxy can regularly poll a cache or watch a file for new *config JSON* versions.
These are the ports used by the Proxy by default:
* **8050**: for standard HTTP communication. ([API](https://configcat.com/docs/advanced/proxy/endpoints.md#api), [CDN proxy](https://configcat.com/docs/advanced/proxy/endpoints.md#cdn-proxy), [Webhook](https://configcat.com/docs/advanced/proxy/endpoints.md#webhook), [SSE](https://configcat.com/docs/advanced/proxy/endpoints.md#sse))
* **8051**: for providing diagnostic data ([status](https://configcat.com/docs/advanced/proxy/monitoring.md#status), [prometheus metrics](https://configcat.com/docs/advanced/proxy/monitoring.md#prometheus-metrics)).
* **50051**: for [gRPC](https://configcat.com/docs/advanced/proxy/grpc.md) communication.
#### Installation[](#installation "Direct link to Installation")
You can install the ConfigCat Proxy from the following sources:
**Docker**
The docker image is available on DockerHub. You can run the image either as a standalone docker container or via `docker-compose`.
* Standalone
* docker-compose
Pull the docker image:
```shell
docker pull configcat/proxy
```
Run the ConfigCat Proxy:
```shell
docker run -d --name configcat-proxy \
-p 8050:8050 -p 8051:8051 -p 50051:50051 \
-e CONFIGCAT_SDKS='{"":""}' \
configcat/proxy
```
docker-compose.yml
```yaml
services:
configcat_proxy:
image: configcat/proxy
environment:
- CONFIGCAT_SDKS={"":""}
ports:
- "8050:8050"
- "8051:8051"
- "50051:50051"
```
To start docker services, execute the following command:
```shell
docker-compose up -f docker-compose.yml -d
```
**Standalone executable**
You can download the executables directly from [GitHub Releases](https://github.com/configcat/configcat-proxy/releases) for your desired platform.
You can then check the [status endpoint](https://configcat.com/docs/advanced/proxy/monitoring.md#status) of the Proxy to ensure it's working correctly: `http://localhost:8051/status`
#### Usage Scenarios[](#usage-scenarios "Direct link to Usage Scenarios")
This section describes the possible ways of how you can use the Proxy from your application. You can decide where you want the actual feature flag evaluation to happen.
* **Local evaluation**: Feature flags are evaluated by a ConfigCat SDK running in your application. The Proxy only provides the data required for the evaluation process.
* **Remote evaluation**: Feature flags are evaluated within the Proxy, your application only gets the result of the evaluation process.
##### 1. Local evaluation using a ConfigCat SDK connected to the Proxy[](#1-local-evaluation-using-a-configcat-sdk-connected-to-the-proxy "Direct link to 1. Local evaluation using a ConfigCat SDK connected to the Proxy")
The Proxy has the ability to forward all information required for feature flag evaluation to ConfigCat SDKs via its [CDN proxy](https://configcat.com/docs/advanced/proxy/endpoints.md#cdn-proxy) endpoint. This means that you can set up your ConfigCat SDK instances to use the Proxy as their data source.
To do this, you have to set the SDK's `baseUrl` option to the Proxy's host.
example.js (Initializing the ConfigCat JS SDK to use the Proxy with SDK Key)
```js
import * as configcat from "@configcat/sdk";
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](#sdk-identifier--sdk-key) it works with, you can use that identifier prefixed with `configcat-proxy/` as the SDK key at the ConfigCat SDK's initialization.
example.js (Initializing the ConfigCat JS SDK to use the Proxy with SDK identifier)
```js
import * as configcat from "@configcat/sdk";
var configCatClient = configcat.getClient(
"configcat-proxy/#SDK-IDENTIFIER#", // SDK identifier prefixed with 'configcat-proxy/'
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
##### 2. Remote evaluation with the Proxy's API endpoints[](#2-remote-evaluation-with-the-proxys-api-endpoints "Direct link to 2. Remote evaluation with the Proxy's API endpoints")
You can leverage the Proxy's server side feature flag evaluation feature by sending simple HTTP requests to the Proxy's API endpoints.
example.js (Evaluating a feature flag with API using SDK key)
```js
const url = "http://localhost:8050/api/eval"; // Proxy API URL with SDK identifier
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"X-ConfigCat-SdkKey": "#YOUR-SDK-KEY#",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](#sdk-identifier--sdk-key) it works with, you can use that identifier in the API endpoint's path instead of the SDK key header.
example.js (Evaluating a feature flag with API using SDK identifier)
```js
const url = "http://localhost:8050/api/#SDK-IDENTIFIER#/eval"; // Proxy API URL
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
You can find the available API endpoints with their HTTP request/response schemas [here](https://configcat.com/docs/advanced/proxy/endpoints.md#api).
##### 3. Remote evaluation with OpenFeature Remote Evaluation Protocol (OFREP)[](#3-remote-evaluation-with-openfeature-remote-evaluation-protocol-ofrep "Direct link to 3. Remote evaluation with OpenFeature Remote Evaluation Protocol (OFREP)")
info
OFREP compatibility is only available from Proxy version [`v2.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0).
info
The OFREP feature of the Proxy is turned OFF by default, to use it, you have to turn it ON with the [OFREP endpoint options](https://configcat.com/docs/advanced/proxy/endpoints.md#available-options-2).
The Proxy conforms to the [OpenFeature Remote Evaluation Protocol](https://github.com/open-feature/protocol), which means it can be used with OFREP compatible OpenFeature providers.
example.js (Initializing the OFREP JS Web provider to use the Proxy with SDK key)
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkKey", "#YOUR-SDK-KEY#"],
],
}),
);
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](#sdk-identifier--sdk-key) it works with, you can use that identifier in the `X-ConfigCat-SdkId` HTTP header.
example.js (Initializing the OFREP JS Web provider to use the Proxy with SDK identifier)
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from "@openfeature/ofrep-web-provider";
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkId", "#SDK-IDENTIFIER#"],
],
}),
);
```
You can find the available OFREP endpoints with their HTTP request/response schemas [here](https://configcat.com/docs/advanced/proxy/endpoints.md#openfeature-remote-evaluation-protocol-ofrep).
##### 4. Remote evaluation and streaming with SSE[](#4-remote-evaluation-and-streaming-with-sse "Direct link to 4. Remote evaluation and streaming with SSE")
The Proxy has the ability to evaluate feature flags and send notifications about subsequent evaluated flag value changes through [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) connections.
example.js (Evaluating a feature flag and listening to changes with SDK key)
```js
const rawData = {
sdkKey: "#YOUR-SDK-KEY#",
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
}
const data = btoa(JSON.stringify(rawData))
const url = "http://localhost:8050/sse/eval/k"; // Proxy SSE URL
const evtSource = new EventSource(url + "/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](#sdk-identifier--sdk-key) it works with, you can use that identifier in the SSE endpoint's path.
example.js (Evaluating a feature flag and listening to changes with SDK identifier)
```js
const rawData = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
}
const data = btoa(JSON.stringify(rawData))
const url = "http://localhost:8050/sse/#SDK-IDENTIFIER#/eval"; // Proxy SSE URL with SDK identifier
const evtSource = new EventSource(url + "/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
For more information and usage examples, see the related [SSE endpoints documentation](https://configcat.com/docs/advanced/proxy/endpoints.md#sse).
##### 5. Remote evaluation and streaming with gRPC[](#5-remote-evaluation-and-streaming-with-grpc "Direct link to 5. Remote evaluation and streaming with gRPC")
The Proxy supports both unary feature flag evaluation RPCs and server streaming of evaluated flag value changes. For more information and usage examples, see the [gRPC section of this documentation](https://configcat.com/docs/advanced/proxy/grpc.md).
#### Configuration Options[](#configuration-options "Direct link to Configuration Options")
You can specify options for the Proxy either via a YAML file or with environment variables. When an option is defined in both places, the environment variable's value takes precedence.
By default, the Proxy reads the options YAML from the following default locations:
* **Windows**: `%PROGRAMDATA%\configcat\proxy\options.yml`, usually `C:\ProgramData\configcat\proxy\options.yml`
* **macOS**: `/Library/Application Support/configcat/proxy/options.yml`
* **Linux**: `/etc/configcat/proxy/options.yml`
When the default location is not suitable, you can specify a custom location for your options YAML file via the `-c` argument.
* YAML
* Environment variables
**Docker**
When running the Proxy in docker, you can mount the options YAML file as a volume.
```shell
docker run -d --name configcat-proxy \
-p 8050:8050 -p 8051:8051 -p 50051:50051 \
-v /options.yml:/etc/configcat/proxy/options.yml
```
(Optional) With the `-c` argument to specify a custom path for your options YAML file:
```shell
docker run -d --name configcat-proxy \
-p 8050:8050 -p 8051:8051 -p 50051:50051 \
-v /options.yml:/cnf/options.yml \
configcat/proxy -c /cnf/options.yml
```
**Standalone executable**
Run the Proxy as a standalone executable with the options YAML file in its default location:
* macOS / Linux
* Windows
```shell
./configcat-proxy
```
```powershell
.\configcat-proxy.exe
```
(Optional) With the `-c` argument to specify a custom path for your options YAML file:
* macOS / Linux
* Windows
```shell
./configcat-proxy -c /path-to-file/options.yml
```
```powershell
.\configcat-proxy.exe -c \path-to-file\options.yml
```
**Docker**
When running the Proxy in docker, you can pass environment variables to the executing container.
```shell
docker run -d --name configcat-proxy \
-p 8050:8050 -p 8051:8051 -p 50051:50051 \
-e CONFIGCAT_SDKS='{"":""}' \
configcat/proxy
```
**Standalone executable**
Make sure the related environment variables are available for the Proxy's hosting process.
* shell
* PowerShell
```shell
export CONFIGCAT_SDKS='{"":""}'
```
Then start the Proxy:
```shell
./configcat-proxy
```
```powershell
$Env:CONFIGCAT_SDKS='{"":""}'
```
Then start the Proxy:
```powershell
.\configcat-proxy.exe
```
The following sections will go through each available option in detail.
#### How does the Proxy learn about feature flags?[](#sdk "Direct link to How does the Proxy learn about feature flags?")
In order to make the Proxy work properly, it must be set up with one or more [SDK keys](https://app.configcat.com/sdkkey). It creates one SDK instance per SDK key internally and uses those for feature flag evaluation.
##### SDK Identifier[](#sdk-identifier--sdk-key "Direct link to SDK Identifier")
Within the Proxy, [SDK keys](https://app.configcat.com/sdkkey) are mapped to unique SDK identifiers.
The *SDK key* identifies a config-environment pair and is used to configure an SDK instance to fetch the config JSON of that config-environment pair. The *SDK identifier* identifies an SDK instance running within the Proxy and configured to use the associated SDK key. That is, the SDK identifier is effectively an alias for the associated SDK key and is used in [endpoint routes](https://configcat.com/docs/advanced/proxy/endpoints.md) to avoid exposing the SDK Key.
There are two ways to let the Proxy know which SDK Keys it should use:
##### 1. Automatic configuration with Proxy profiles[](#1-automatic-configuration-with-proxy-profiles "Direct link to 1. Automatic configuration with Proxy profiles")
info
**Beta Feature**: Automatic configuration with Proxy profiles is in public beta. We're now collecting feedback from real-world usage to fine-tune the experience. Share your feedback [here](https://configcat.com/support).
info
The automatic configuration with Proxy profiles feature is only available from Proxy version [`v2.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0).
The Proxy has the ability to use *Proxy profiles* to determine which SDK keys to download and distribute. It periodically checks for profile changes, allowing it to pick up the changes on the fly, without needing a restart.
By using Proxy profiles, your deployed Proxy instances can detect and react to:
* SDK key rotation.
* Data governance change.
* Product, config and environment state changes, such as creation, renaming and deletion.
You can set up Proxy profiles under the `Manage organization` -> `Proxy Profiles` menu on the [ConfigCat Dashboard](https://app.configcat.com/organization/proxy-profiles).

To connect a Proxy instance to a Proxy profile, follow these steps:
* ###### Create a new Proxy profile[](#create-a-new-proxy-profile "Direct link to Create a new Proxy profile")
Click on the `+ ADD PROFILE` button.

Give the profile a meaningful name and description, then click `CREATE`.

* ###### Configure your Proxy instance[](#configure-your-proxy-instance "Direct link to Configure your Proxy instance")
Grab the `Key` and `Secret` from the profile creation dialog and put them into the Proxy's configuration.

* YAML
* Environment variables
options.yml
```yaml
profile:
key:
secret:
```
```shell
CONFIGCAT_PROFILE_KEY=""
CONFIGCAT_PROFILE_SECRET=""
```
* ###### Select which SDK Keys your Proxy should use[](#select-which-sdk-keys-your-proxy-should-use "Direct link to Select which SDK Keys your Proxy should use")
Click on the edit icon in the `SDK Keys` column.

You can choose SDK Keys in two ways: by creating selection rules or by choosing individual SDK Keys manually. Your applications will have access to all feature flags in the config-environment pairs whose SDK Keys you select.
* ###### Selection rules[](#selection-rules "Direct link to Selection rules")
With selection rules, you can describe which existing and future config-environment pairs should be distributed to Proxy instances. Rules can be based on products, configs and environments with the following filtering options:
* **Exact** (by selecting an exact product, config or environment): This option filters for the ID of the selected product, config or environment. It's not sensitive to renaming.
* **Any**: This option is similar to a single wildcard (`*`) expression. It filters for every product, config or environment.
* **Match expression** (by selecting `Matches`): This option matches the given pattern to the name of products/configs/environments, accepting wildcards (`*`). It's sensitive to renaming.
Whenever a config-environment pair matches both an **Include** and an **Exclude** rule, the **Exclude** rule will always take precedence.

* ###### Manual selection[](#manual-selection "Direct link to Manual selection")
You can manually select the config-environment pairs whose SDK key you want to make available for your Proxy instance.

info
You can click config names in the first column to toggle all SDK keys in a row, or environment names in the column headers to toggle all SDK keys in a column.
* ###### Locate SDK identifiers for the selected SDK Keys[](#locate-sdk-identifiers-for-the-selected-sdk-keys "Direct link to Locate SDK identifiers for the selected SDK Keys")
You can find the SDK identifiers generated for the selected config-environment pairs on the ConfigCat Dashboard right where you find their SDK Key.

In the dialog that appears, you can find the SDK identifiers for the current config-environment pair, listed for each available Proxy profile.

* ###### (Optional) Set up how your Proxy should learn about feature flag changes[](#optional-set-up-how-your-proxy-should-learn-about-feature-flag-changes "Direct link to (Optional) Set up how your Proxy should learn about feature flag changes")
There are two ways a Proxy can detect feature flag changes. Each config-environment pair identified by each SDK key is automatically monitored for changes by periodic polling of the corresponding config JSON file at a configured frequency. Besides polling, the Proxy can receive change notifications over HTTP, via its [webhook endpoint](https://configcat.com/docs/advanced/proxy/endpoints.md#webhook).
* ###### Config JSON poll interval[](#config-json-poll-interval "Direct link to Config JSON poll interval")
You have the option to control how frequently the Proxy should poll for config JSON changes. Click on the configure icon in the `Connection preferences` column, set the poll interval and click on `SAVE POLL INTERVAL`.

* ###### Webhook notification[](#webhook-notification "Direct link to Webhook notification")
You can set up automatic webhook notifications about feature flag changes for your Proxy by providing its public URL. Click on the configure icon in the `Connection preferences` column and select `Webhook notification`. Then, enter your Proxy instance's public URL and click `ADD PROXY URL`.

Put the displayed webhook signing key(s) into your Proxy's configuration. Signing keys are for making sure that webhook requests received by your Proxy are sent by ConfigCat. Signatures are automatically [verified](https://configcat.com/docs/advanced/notifications-webhooks.md#verifying-webhook-requests) by the Proxy.

* YAML
* Environment variables
options.yml
```yaml
profile:
webhook_signing_key:
```
```shell
CONFIGCAT_PROFILE_WEBHOOK_SIGNING_KEY=""
```
Test the connection to your Proxy instance.

* ###### All configuration options related to Proxy profiles[](#all-configuration-options-related-to-proxy-profiles "Direct link to All configuration options related to Proxy profiles")
| Option | Default | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML - Environment variable\`\`\`yaml
profile:
key: ""
```````shell
CONFIGCAT_PROFILE_KEY=""
``` | - | The Proxy profile's key. |
| - YAML - Environment variable```yaml
profile:
secret: ""
``````shell
CONFIGCAT_PROFILE_SECRET=""
``` | - | The Proxy profile's secret used by the Proxy to authenticate requests to the Public Management API. |
| - YAML - Environment variable```yaml
profile:
base_url: ""
``````shell
CONFIGCAT_PROFILE_BASE_URL=""
``` | ConfigCat Public Management API URL | The base URL from where the Proxy should fetch the SDK Keys selected in the connected Proxy profile. |
| - YAML - Environment variable```yaml
profile:
poll_interval: 300
``````shell
CONFIGCAT_PROFILE_POLL_INTERVAL=300
``` | 300 | The interval (in seconds) specifying how frequently the Proxy should poll for changes in the connected Proxy profile. |
| - YAML - Environment variable```yaml
profile:
webhook_signing_key: ""
``````shell
CONFIGCAT_PROFILE_WEBHOOK_SIGNING_KEY=""
``` | - | The [key used to sign](https://configcat.com/docs/advanced/notifications-webhooks.md#calculating-signature) the webhook requests sent to the Proxy. [More about how to set up webhooks for a Proxy profile](#webhook-notification). |
| - YAML - Environment variable```yaml
profile:
webhook_signature_valid_for: 300
``````shell
CONFIGCAT_PROFILE_WEBHOOK_SIGNATURE_VALID_FOR=300
``` | 300 | The time period (in seconds) within which webhook requests are considered valid. [More about how to set up webhooks for a Proxy profile](#webhook-notification). |
| - YAML - Environment variable```yaml
profile:
log:
level: ""
``````shell
CONFIGCAT_PROFILE_LOG_LEVEL=""
``` | `warn` | The verbosity level for Proxy profile-related logging. Possible values: `error`, `warn`, `info`, or `debug`. |
| - YAML - Environment variable```yaml
profile:
sdks:
base_url: ""
``````shell
CONFIGCAT_PROFILE_SDKS_BASE_URL=""
``` | ConfigCat's CDN URL. | The CDN base URL (forward proxy, dedicated subscription) from where the ConfigCat SDKs should download the config JSON. |
| - YAML - Environment variable```yaml
profile:
sdks:
log:
level: ""
``````shell
CONFIGCAT_PROFILE_SDKS_LOG_LEVEL=""
``` | `warn` | The verbosity level for logging performed by the ConfigCat SDKs spawned for the connected Proxy profile. Possible values: `error`, `warn`, `info`, or `debug`. |
#### Profile caching[](#profile-caching "Direct link to Profile caching")
Proxy instances running in online mode are caching their connected profile if they have a [cache](#cache) configured. This means that other Proxy instances running with [global offline mode](#global-offline-mode) enabled can use those cached profiles from the same shared cache.
info
Offline Proxy instances only need the profile's `key` to read the connected profile from the cache, the `secret` option is not mandatory in this mode.
```````
##### 2. Manual configuration[](#2-manual-configuration "Direct link to 2. Manual configuration")
When using environment variables, the SDK keys can be specified as a JSON object, where the **property name is the SDK identifier** (the identifier of the config-environment pair whose SDK Key the underlying SDK instance is configured to use) and the **property value is the actual SDK key**. The **SDK identifier** part is later used in [endpoint routes](https://configcat.com/docs/advanced/proxy/endpoints.md) to recognize which SDK must serve the given flag evaluation request.
Furthermore, when configuring the Proxy **via environment variables**, the identifier becomes a **part of the SDK specific environment variable's name** in the following format: `CONFIGCAT__