flagd basics
Your flagd journey will start by defining your feature flags.
flagd will then read those feature flags and make them available to your application.
Your application will interact with flagd via the OpenFeature SDK to retrieve flag values via the flagd API.
Defining feature flags
Flags can be defined in either JSON or YAML syntax and the values can be of different types.
Here are two flags, flagOne
has boolean
values and flagTwo
has string
values.
flags represented as JSON
{
"flags": {
"flagOne": {
"state": "ENABLED",
"variants": {
"on": true,
"off": false
},
"defaultVariant": "on",
"targeting": {}
},
"flagTwo": {
"state": "ENABLED",
"variants": {
"key1": "val1",
"key2": "val2"
},
"defaultVariant": "key1",
"targeting": {}
}
}
}
flags represented as YAML
flags:
flagOne:
state: ENABLED
variants:
'on': true
'off': false
defaultVariant: 'on'
targeting:
flagTwo:
state: ENABLED
variants:
key1: val1
key2: val2
defaultVariant: 'key1'
targeting:
The structure of a flag
Each flag has:
- A flag key:
flagOne
andflagTwo
above - A state:
ENABLED
orDISABLED
- One or more possible
variants
. These are the possible values that a flag key can take. - An optional
targeting
rule (explained below)
Targeting rules
Imagine you are introducing a new feature. You create a flag with two possible variants: on
and off
. You want to safely roll out the feature.
Therefore the flags defaultValue
is set to off
for all users.
In other words, the new feature is disabled by default.
Now imagine you want to enable the feature, but only when the following is true:
- Logged in users where the user's email ends in
@example.com
Rather than codifying that in your application, flagd targeting rules can be used. The flag definition below models this behaviour.
When a user logs into your application, your application is responsible for sending the email
address via OpenFeature's context parameter (see below) and flagd will return the correct flag.
If the email address of the logged in users contains @example.com
then flagd will return the on
variant (ie. true
).
All other users receives the defaultVariant
of off
(ie. false).
In this context, "all other users" means:
- Any logged in user whos email does not contain
@example.com
- Any logged out user
Your application is responsible for sending the email
address via OpenFeature's context parameter (see below) and flagd will return the correct flag.
{
"flags": {
"isFeatureEnabled": {
"state": "ENABLED",
"variants": {
"on": true,
"off": false
},
"defaultVariant": "off",
"targeting": {
"if": [{
"in": [
"@example.com",
{
"var": ["email"]
}]
},
"on", null]
}
}
}
}
Pseudo-code of application passing context
// Here, we provide an empty context, hence the flag evaluates to false value which is the defaultVariant
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {}) // false
// Here, we provide email for the flag evaluation. Still flag evaluates to defaultVariant of false as email does not end with desired domain
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {"email": "example@gmail.com"}) // false
// Here, the flag is evaluated with targeting rule matching, hence the value of true
featureAvailable = openFeature.getBooleanValue("isFeatureEnabled", false, {"email": "someone@example.com"}) // true
Fractional Evaluation
In some scenarios, it is desirable to use contextual information to segment the user population further and thus return dynamic values.
Look at the headerColor
flag below. The defaultVariant
is red
, but the flag contains a targeting rule, meaning a fractional evaluation occurs when a context is passed and a key of email
contains the value @example.com
.
In this case, 25%
of the email addresses will receive red
, 25%
will receive blue
, and so on.
{
"flags": {
"headerColor": {
"variants": {
"red": "#FF0000",
"blue": "#0000FF",
"green": "#00FF00",
"yellow": "#FFFF00"
},
"defaultVariant": "red",
"state": "ENABLED",
"targeting": {
"if": [{
"emailWithFaas": {
"in": ["@faas.com", {
"var": ["email"]
}]
}
},
{
"fractional": [
{ "var": "email" },
[ "red", 25 ], [ "blue", 25 ], [ "green", 25 ], [ "yellow", 25 ]
]
}, null
]
}
}
}
}
Fractional evaluations are sticky
Fractional evaluations are "sticky" (deterministic) meaning that the same email address will always belong to the same "bucket" and thus always receive the same color. This is true even if you run multiple flagd instances completely independently.
Note that the first argument to the fractional
operator is an expression specifying the bucketing value.
This value is used as input to the bucketing algorithm to ensure a deterministic result.
This argument can be omitted, in which case a concatenation of the targetingKey
and the flagKey
will be used as the bucketing value.
See this page for more information on flagd fractional evaluation logic.
Migrating from legacy fractionalEvaluation
If you are using a legacy fractional evaluation (fractionalEvaluation
), it's recommended you migrate to fractional
.
The new fractional
evaluator supports nested properties and JsonLogic expressions.
To migrate, simply use a JsonLogic variable declaration for the bucketing property, instead of a string:
old:
"fractionalEvaluation": [
"email",
[ "red", 25 ], [ "blue", 25 ], [ "green", 25 ], [ "yellow", 25 ]
]
new:
"fractional": [
{ "var": "email" },
[ "red", 25 ], [ "blue", 25 ], [ "green", 25 ], [ "yellow", 25 ]
]
Other target specifiers
The example above shows the in
keyword being used, but flagd is also compatible with:
flagd OpenTelemetry
flagd is fully compatible with OpenTelemetry:
- flagd exposes metrics at
http://localhost:8014/metrics
- flagd can export metrics and traces to an OpenTelemetry collector.
See the flagd OpenTelemetry page for more information.