-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Todd Baert <[email protected]>
- Loading branch information
Showing
73 changed files
with
1,649 additions
and
1,696 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,4 +14,5 @@ go.work.sum | |
bin/ | ||
|
||
# built documentation | ||
site | ||
site | ||
.cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Architecture | ||
|
||
flagd architectures fall into two broad categories: those where the evaluation engine is deployed in a standalone process to which the client application connects ([RPC](#rpc-evaluation)), and those where the evaluation engine is embedded into the client application ([in-process](#in-process-evaluation)). | ||
|
||
## RPC vs In-Process Evaluation | ||
|
||
### RPC evaluation | ||
|
||
In RPC-based deployments one or more flagd instances deployed and exposed to client applications in your infrastructure. | ||
flagd RPC providers use HTTP or gRPC to request flag evaluations from flagd. | ||
The request payload contains the [flag key](https://openfeature.dev/specification/glossary#flag-key) identifying the flag to be evaluated, as well as the relevant [evaluation context](https://openfeature.dev/specification/glossary#evaluation-context). | ||
The flagd instance is configured to watch one or more [syncs](./concepts/syncs.md), and merges them to build its set of flags (see [here](./concepts/syncs.md#merging) for more details on flag definition merging). | ||
When sync sources are updated, flagd will send notifications to clients that flags have changed, enabling applications to react to changes by re-evaluating flags. | ||
|
||
This architecture is can be leveraged by very simple clients, since no in-process engine is needed; in fact, you can evaluate flags directly from a terminal console using the `cURL` utility. | ||
One disadvantage of this pattern is the latency involved in the remote request (though flagd typically takes <10ms for an evaluation, and can evaluate thousands of flags per second). | ||
|
||
```mermaid | ||
--- | ||
title: RPC Evaluation | ||
--- | ||
erDiagram | ||
flagd ||--o{ "sync (file)" : watches | ||
flagd ||--o{ "sync (http)" : polls | ||
flagd ||--o{ "sync (grpc)" : "sync.proto (gRPC/stream)" | ||
flagd ||--o{ "sync (kubernetes)" : watches | ||
"client app (+ flagd RPC provider)" ||--|| flagd : "evaluation.proto (gRPC/stream) / HTTP" | ||
``` | ||
|
||
### In-Process evaluation | ||
|
||
In-process deployments embed the flagd evaluation engine directly into the client application through the use of an [in-process provider](./deployment.md#in-process). | ||
The in-process provider is connected via the sync protocol to an implementing [gRPC service](./concepts/syncs.md#grpc-sync) that provides the flag definitions. | ||
This pattern requires an in-process implementation of the flagd evaluation engine, but has the benefit of no I/O overhead, since no inter-process communication is required. | ||
|
||
```mermaid | ||
--- | ||
title: In-Process Evaluation | ||
--- | ||
erDiagram | ||
"client app (+ flagd in-process provider)" ||--|| "sync (grpc)" : "sync.proto (gRPC/stream)" | ||
``` | ||
|
||
<!-- TODO: add link to sync protocol reference entry --> | ||
<!-- TODO: we might want a dedicated Kubernets section here eventually to talk about the specifics of the K8s implementation --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"flags": { | ||
"show-welcome-banner": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"on": true, | ||
"off": false | ||
}, | ||
"defaultVariant": "off" | ||
}, | ||
"background-color": { | ||
"state": "ENABLED", | ||
"variants": { | ||
"red": "#FF0000", | ||
"blue": "#0000FF", | ||
"green": "#00FF00", | ||
"yellow": "#FFFF00" | ||
}, | ||
"defaultVariant": "red" | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Feature Flagging | ||
|
||
Feature flags are a software development technique that allows teams to enable, disable or change the behavior of certain features or code paths in a product or service, without modifying the source code. | ||
|
||
## OpenFeature Compliance | ||
|
||
[OpenFeature](https://openfeature.dev/) is an open standard that provides a vendor-agnostic, community-driven API for feature flagging. | ||
The flagd project is fully OpenFeature-compliant. | ||
In fact, flagd was initially conceived as a reference implementation for an OpenFeature backend, but has become a powerful tool in its own right. | ||
For this reason, you'll find flagd's concepts and terminology align with that of the OpenFeature project. | ||
Within the context of an OpenFeature-compliant feature flag solution, flagd artifacts and libraries comprise the [flag management system](https://openfeature.dev/specification/glossary#flag-management-system) and [providers](https://openfeature.dev/specification/glossary#provider). | ||
These artifacts and libraries alone won't allow you to evaluate flags in your application - you'll also need the [OpenFeature SDK](https://openfeature.dev/specification/glossary#feature-flag-sdk) for your language as well, which provides the evaluation API for application developers to use. | ||
|
||
## Supported Feature Flagging Use-Cases | ||
|
||
Below is a non-exhaustive table of common feature flag use-cases, and how flagd supports them: | ||
|
||
| Use case | flagd Feature | | ||
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| flag evaluation | Returns the value of a particular feature flag, if the flag is enabled. Supports flags of various types including boolean, numeric, string, and JSON. | | ||
| dynamic configuration | Flag definitions from any sync source are monitored for changes, with some syncs supporting near real time updates. | | ||
| dynamic (context-sensitive) evaluation | flagd evaluations are context sensitive. Rules can use arbitrary context attributes as inputs for flag evaluation logic. | | ||
| fractional evaluation / random assignment | flagd's [fractional](../reference/custom-operations/fractional-operation.md) custom operation supports pseudorandom assignment of flag values. | | ||
| progressive roll-outs | Progressive roll-outs of new features can be accomplished by leveraging the [fractional](../reference/custom-operations/fractional-operation.md) custom operation as well as automation in your build pipeline, SCM, or infrastructure which updates the distribution over time. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Syncs | ||
|
||
Syncs are a core part of flagd; they are the abstraction that enables different sources for feature flag definitions. | ||
flagd can connect to one or more sync sources to | ||
|
||
## Available syncs | ||
|
||
### Filepath sync | ||
|
||
The file path sync provider reads and watch the source file for updates(ex: changes and deletions). | ||
|
||
```shell | ||
flagd start --uri file:etc/featureflags.json | ||
``` | ||
|
||
In this example, `etc/featureflags.json` is a valid feature flag definition file accessible by the flagd process. | ||
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details. | ||
|
||
--- | ||
|
||
### HTTP sync | ||
|
||
The HTTP sync provider fetch flags from a remote source and periodically poll the source for flag definition updates. | ||
|
||
```shell | ||
flagd start --uri https://my-flag-source.json | ||
``` | ||
|
||
In this example, `https://my-flag-source.json` is a remote endpoint responding valid feature flag definition when | ||
invoked with **HTTP GET** request. | ||
The polling interval, port, TLS settings, and authentication information can be configured. | ||
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details. | ||
|
||
--- | ||
|
||
### gRPC sync | ||
|
||
The gRPC sync provider streams flag definition from a gRPC sync provider implementation. This stream connection is ruled | ||
by | ||
the [sync service protobuf definition](https://github.com/open-feature/schemas/blob/main/protobuf/sync/v1/sync_service.proto). | ||
|
||
```shell | ||
flagd start --uri grpc://grpc-sync-source | ||
``` | ||
|
||
In this example, `grpc-sync-source` is a grpc target implementing [sync.proto](../reference/flag-sync-protocol.md) definition. | ||
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details. | ||
|
||
--- | ||
|
||
### Kubernetes sync | ||
|
||
The Kubernetes sync provider allows flagd to connect to a Kubernetes cluster and evaluate flags against a specified | ||
FeatureFlagConfiguration resource as defined within | ||
the [open-feature-operator](https://github.com/open-feature/open-feature-operator/blob/main/apis/core/v1alpha1/featureflagconfiguration_types.go) | ||
spec. | ||
This configuration is best used in conjunction with the [OpenFeature Operator](https://github.com/open-feature/open-feature-operator). | ||
|
||
To use an existing FeatureFlagConfiguration custom resource, start flagD with the following command: | ||
|
||
```shell | ||
flagd start --uri core.openfeature.dev/default/my_example | ||
``` | ||
|
||
In this example, `default/my_example` expected to be a valid FeatureFlagConfiguration resource, where `default` is the | ||
namespace and `my_example` being the resource name. | ||
See [sync source](../reference/sync-configuration.md#source-configuration) configuration for details. | ||
|
||
## Merging | ||
|
||
Flagd can be configured to read from multiple sources at once, when this is the case flagd will merge all flag definition into a single | ||
merged state. | ||
|
||
For example: | ||
|
||
![flag merge 1](../images/flag-merge-1.svg) | ||
|
||
In this example, `source-A` and `source-B` provide a single flag definition, the `foo` flag and the `bar` flag respectively. | ||
The merge logic for this definition is simple, both flag definition are added to the `store`. | ||
|
||
In most scenarios, these flag sources will be supplying `n` number of definition, using a unique flag key for each definition. | ||
|
||
However, as multiple sources are being used, there is the opportunity for keys to be duplicated, intentionally or not, between flag sources. | ||
In these situations `flagd` uses a merge priority order to ensure that its behavior is consistent. | ||
|
||
Merge order is dictated by the order that `sync-providers` and `uris` are defined, with the latest defined source taking precedence over those defined before it, as an example: | ||
|
||
```sh | ||
./bin/flagd start --uri file:source-A.json --uri file:source-B.json --uri file:source-C.json | ||
``` | ||
|
||
When `flagd` is started with the command defined above, `source-B` takes priority over `source-A`, whilst `source-C` takes priority over both `source-B` and `source-A`. | ||
|
||
Using the above example, if a flag key is duplicated across all 3 sources, then the definition from `source-C` would be the only one stored in the merged state. | ||
|
||
![flag merge 2](../images/flag-merge-2.svg) | ||
|
||
### State Resync Events | ||
|
||
Given the above example, the `source-A` and `source-B` 'versions' of flag definition the `foo` have been discarded, so if a delete event in `source-C` results in the removal of the `foo`flag, there will no longer be any reference of `foo` in flagd's store. | ||
|
||
As a result of this flagd will return `FLAG_NOT_FOUND` errors, and the OpenFeature SDK will always return the default value. | ||
|
||
To prevent flagd falling out of sync with its flag sources during delete events, resync events are used. | ||
When a delete event results in a flag definition being removed from the merged state, the full set of definition is requested from all flag sources, and the merged state is rebuilt. | ||
As a result, the value of the `foo` flag from `source-B` will be stored in the merged state, preventing flagd from returning `FLAG_NOT_FOUND` errors. | ||
|
||
![flag merge 3](../images/flag-merge-3.svg) | ||
|
||
In the example above, a delete event results in a resync event being fired, as `source-C` has deleted its 'version' of the `foo`, this results in a new merge state being formed from the remaining definition. | ||
|
||
![flag merge 4](../images/flag-merge-4.svg) | ||
|
||
Resync events may lead to further resync events if the returned flag definition result in further delete events, however the state will eventually be resolved correctly. |
Oops, something went wrong.