Skip to content

Commit b604574

Browse files
docs: first draft multi-sync-sources ADR (#1636)
Intent of this PR is to add the first draft of the multi-synch-sources ADR, this is a docs-only change --------- Signed-off-by: Dave Josephsen <[email protected]> Signed-off-by: Todd Baert <[email protected]> Co-authored-by: Todd Baert <[email protected]>
1 parent b638441 commit b604574

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

docs/architecture-decisions/multiple-flag-set-support.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ created: 2025-05-28
55
updated: -
66
---
77

8-
⚠️ REJECTED IN FAVOR OF https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/duplicate-flag-keys.md ⚠️
9-
108
# Add support for dynamic usage of Flag Sets to `flagd`
119

10+
⚠️ REJECTED IN FAVOR OF <https://github.com/open-feature/flagd/blob/main/docs/architecture-decisions/duplicate-flag-keys.md> ⚠️
11+
1212
The goal of this decision document is to establish flag sets as a first class concept in `flagd`, and support the dynamic addition/update/removal of flag sets at runtime.
1313

1414
## Background
@@ -142,7 +142,7 @@ final FlagdProvider flagdProvider =
142142

143143
### Other Options
144144

145-
We evaluated the [mentioned options](#considered_options) as follows: _options 2 + 3: support for dynamically adding/removing flag sources_ and decided against this option because it requires much more implementation effort than _option 1_. Required changes include:
145+
We evaluated the [mentioned options](#considered-options) as follows: _options 2 + 3: support for dynamically adding/removing flag sources_ and decided against this option because it requires much more implementation effort than _option 1_. Required changes include:
146146

147147
* flagd/core/sync: dynamic mode, which allows specifying the sync type that should be added/removed at runtime
148148
* flagd/flagd: startup dynamic sync configuration
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
status: accepted
3+
author: Dave Josephsen
4+
created: 2025-05-21
5+
updated: 2025-05-21
6+
---
7+
8+
# ADR: Multiple Sync Sources
9+
10+
It is the Intent of this document to articulate our rationale for supporting multiple flag syncronization sources (grpc, http, blob, local file, etc..) as a core design property of flagd. This document also includes a short discussion of how flagd is engineered to enable the community to extend it to support new sources in the future, to "future proof" the runtime against sources that don't yet exist, or those we may have omitted is a requisite byproduct of this architectural decision.
11+
12+
The goal of first-class multi-sync support generally is to broaden flagd's potential to suit the needs of many different types of users or architecture. By decoupling flag persistence from the runtime, flagd can focus on evaluation and sync, while enabling its user-base to choose a persistence layer that best suits their individual requirements.
13+
14+
## Background
15+
16+
The flagd daemon is a feature flag evaluation engine that forms a core part of the OpenFeature ecosystem as a production-grade reference implementation. Unlike OpenFeature SDK components, which are, by design, agnostic to the specifics of flag structure, evaluation, and persistence, flagd must take an opinionated stance about how feature-flags look, feel, and act.
17+
What schema best describes a flag? How should they be evaluated? And in what sort of persistence layer should they be stored?
18+
19+
This latter-most question -- _how should they be stored_ -- is the most opaque design detail of every commercial flagging product from the perspective its end-users.
20+
As a front-line engineer using a commercial flagging product, I may, for example, be exposed to flag schema by the product's SDK, and become familiar with its evaluation intricacies over time as my needs grow to require advanced features, or as I encounter surprising behavior. Rarely, however, is an end-user exposed to the details of a commercial product's storage backend.
21+
The SaaS vendor is expected to engineer a safe, fast, multi-tenant storage back-end, optimized for its flag schema and operational parameters, and insulate the customer from these details via its SDK.
22+
This presents Flagd, an open-source evaluation engine, with an interesting conundrum: what sort of flag storage best suits the needs of its potential user-base (which is everyone)?
23+
24+
## Requirements
25+
26+
* Support the storage technology that's most likely to meet the needs of current Flagd user-base (Don't be weird. Don't be surprising.)
27+
* Make it "easy" to extend the flagd runtime to support "new" storage systems
28+
* Horizontally scalable persistence layer
29+
* Minimize end-user exposure to persistence "quirks" (replication schemes, leader election, back-end scaling, consistency minutia, etc.. )
30+
* Reliable, Fast, Transparent
31+
* Full CRUD, read-optimized.
32+
33+
## Considered Options
34+
35+
* Be super-opinionated and prescribe a built-in raftesque key-value setup, analogous to the designs of k8s and kafka, which prescribe etcd and zookeeper respectively.
36+
* Roll a single "standard interface" for flag sync (published grpc spec or similar) (??)
37+
* Decouple storage from flagd entirely, by exposing a Golang interface type that "providers" can implement to provide support for any data store.
38+
39+
## Proposal
40+
<!--
41+
Unsure whether we want a diagram in this section or not. Happy to add one if we want one.
42+
-->
43+
The solution to the conundrum posited in the background section of this document is to decouple flag storage entirely from the rest of the runtime, including instead support for myriad commonly used data syncronization interfaces.
44+
This allows Flagd to be agnostic to flag storage, while enabling users to use whichever storage back-end best suits their environment.
45+
46+
To extend Flagd to support a new storage back-end, _sync providers_ implement the _ISync_ interface, detailed below:
47+
48+
```go
49+
type ISync interface {
50+
// Init is used by the sync provider to initialize its data structures and external dependencies.
51+
Init(ctx context.Context) error
52+
53+
// Sync is the contract between Runtime and sync implementation.
54+
// Note that, it is expected to return the first data sync as soon as possible to fill the store.
55+
Sync(ctx context.Context, dataSync chan<- DataSync) error
56+
57+
// ReSync is used to fetch the full flag configuration from the sync
58+
// This method should trigger an ALL sync operation then exit
59+
ReSync(ctx context.Context, dataSync chan<- DataSync) error
60+
61+
// IsReady shall return true if the provider is ready to communicate with the Runtime
62+
IsReady() bool
63+
}
64+
```
65+
66+
syncronization events "fan-in" from all configured sync providers to flagd's in-memory state-store via a channel carrying [`sync.DataSync`](https://github.com/open-feature/flagd/blob/main/core/pkg/store/flags.go#L19) events.
67+
These events detail the source and type of the change, along with the flag data in question and are merged into the currently held state by the [store](https://github.com/open-feature/flagd/blob/main/core/pkg/store/flags.go#L19).
68+
69+
### Consequences
70+
71+
Because syncronization providers may vary wildly with respect to their implementation details, supporting multiple sync providers means supporting custom configuration parameters for each provider.
72+
As a consequence, Flagd's configuration is itself made more complex, and its bootstrap process, whose goal is to create a [`runtime.Runtime`](https://github.com/open-feature/flagd/blob/main/flagd/pkg/runtime/runtime.go#L21) object from user-provided configuration, spends the preponderance of its time and effort interpreting, configuring, and initializing sync providers.
73+
There is, in fact, a custom bootstrap type, called the `syncbuilder` whose job is to bootstrap sync providers and arrange them into a map, for the runtime to use.
74+
75+
Further, Because sync providers may vary wildly with respect to implementation, the end-user's choice of sync sources can change Flagd's operational parameters. For example, end-users who choose the GRPC provider can expect flag-sync operations to be nearly immediate, because GRPC updates can be pushed to flagd as they occur, compared with end-users who chose the HTTP provider, who must wait for a timer to expire in order to notice updates, because HTTP is a polling-based implementation.
76+
77+
Finally, sync Providers also contribute a great deal of girth to flagd's documentation, because again, their setup, syntax, and runtime idiosyncrasies may differ wildly.

0 commit comments

Comments
 (0)