Skip to main content
Version: Config V2

Details of LaunchDarkly to ConfigCat Translation

This document discusses the details of how ConfigCat's "Import from LaunchDarkly" tool 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

The table below shows how LaunchDarkly entities are mapped to ConfigCat entities.

LaunchDarkly entityCorresponding ConfigCat entityNotes
projectproduct
environmentenvironment
segmentsegmentLaunchDarkly 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 flagfeature flag / settingLaunchDarkly feature flags are directly contained by a project, but ConfigCat feature flags are organized into configs, so a config named "Main Config" is created to contain them.
targeting toggle-No direct translation is possible. More on this here.
prerequisites-Each prerequisite is translated to a Targeting Rule containing a Flag Condition.
individual targets-Each target group is translated to a Targeting Rule containing an IS ONE OF User Condition.
custom ruleTargeting RuleMultiple clauses (i.e. AND conditions in ConfigCat's terminology) are not supported for segments, only for feature flags at the moment.
custom rule clauseUser Condition or Segment ConditionSome LaunchDarkly clauses cannot be translated to ConfigCat conditions with the same evaluation behavior, or at all. See also translation issues
clause attribute referencecomparison attributeLaunchDarkly context attribute paths don't always translate to ConfigCat user attribute names directly. See also this section.
clause operatorcomparatorMost 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 valuescomparison valueAs opposed to LaunchDarkly, not all counterparts of operators support multiple values.
percentage rolloutPercentage OptionsIn LaunchDarkly, the basis of the grouping can be set for each percentage rollout, while in ConfigCat Percentage Evaluation Attribute can only be set at the feature flag level.
default ruletrivial / fallback rule

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, while ConfigCat offers User Objects 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 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 kindLaunchDarkly context attribute pathCorresponding ConfigCat user attribute name
not specified or userempty string or //
not specified or userkey or /keyIdentifier
not specified or useremail or /emailEmail
not specified or usercountry or /countryCountry
not specified or userIdentifier or /Identifier/Identifier
not specified or userEmail or /Email/Email
not specified or userCountry or /Country/Country
not specified or username or /namename
not specified or user/address/city/address/city
deviceempty string or /device:/
devicename or /namedevice:name
organizationname or /nameorganization:name
organization/address/cityorganization:/address/city
anykind 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

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

info

Usually these issues arise when you are on a lower plan, and hitting a subscription limit. If this prevents you from migrating to ConfigCat, feel free to contact us.

CodeLevelIssueWhat 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.

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.

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.

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.

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.

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.

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.

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

CodeLevelIssueWhat 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: "" (empty string)
  • 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", and

  1. 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).

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", and

  1. 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).

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 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.

Data consistency

CodeLevelIssueWhat 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

  • 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 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). 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.