Skip to content

Commit 797b482

Browse files
authored
docs(ADR): support flags with duplicate keys. (#1660)
This is proposal for support flags with duplicate keys, as a follow up of the discussion on #1634 and #1644. The selector semantics change proposed in #1644 will be addressed in a separate ADR. --------- Signed-off-by: Hugo Huang <lorqor@gmail.com>
1 parent caa0ed0 commit 797b482

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
status: proposed
3+
author: @tangenti
4+
created: 2025-06-27
5+
updated: 2025-06-27
6+
---
7+
8+
# Support for Duplicate Flag Keys
9+
10+
This ADR proposes allowing a single sync source to provide multiple flags that share the same key. This enables greater flexibility for modularizing flag configurations.
11+
12+
## Background
13+
14+
Currently, the `flagd` [flag configuration](https://flagd.dev/schema/v0/flags.json) stores flags in a JSON object (a map), where each key must be unique. While the JSON specification technically allows duplicate keys, it's not recommended and not well-supported in the implementations.
15+
16+
This limitation prevents use cases for flag modularization and multi-tenancy, such as:
17+
18+
- **Component-based Flags:** Two different services, each with its own in-process provider, cannot independently define a flag with the same key when communicating with the same `flagd` daemon.
19+
- **Multi-Tenant Targeting:** A single flagd daemon cannot use the same flag key with different targeting rules for different tenants
20+
21+
## Requirements
22+
23+
- Allow a single sync source to define multiple flags that have the same key.
24+
- Flags from a sync source with the same keys can have different types and targeting rules.
25+
- No breaking changes for the current flagd flag configuration schema or flagd sync services.
26+
27+
## Proposal
28+
29+
We will update the `flagd` flag configuration schema to support receiving flags as an **array of flag objects**. The existing schema will remain fully supported.
30+
31+
### API Change
32+
33+
#### Flag Configuration Schema
34+
35+
We'll add a new schema as a [subschema](https://json-schema.org/learn/glossary#subschema) to the existing flagd flag configuration schema. It will be a composite of the original schema except `flags` (`#/definitions/base`), with a new schema for `flags` that allows flags array in addition to the currently supported flags object. The existing main schema will be the composite of `#/definitions/base` and the subschema for the flags object.
36+
37+
```json
38+
...
39+
"flagsArray": {
40+
"type": "array",
41+
"items": {
42+
"allOf": [
43+
{
44+
"$ref": "#/definitions/flag"
45+
},
46+
{
47+
"type": "object",
48+
"properties": {
49+
"key": {
50+
"description": "Key of the flag",
51+
"type": "string",
52+
"minLength": 1
53+
}
54+
},
55+
"required": [
56+
"key"
57+
]
58+
}
59+
]
60+
}
61+
},
62+
"flagsArraySchema": {
63+
"$id": "https://flagd.dev/schema/v0/flags.json#flagsarray",
64+
"type": "object",
65+
"allOf": [
66+
{
67+
"$ref": "#/definitions/base"
68+
},
69+
{
70+
"properties": {
71+
"flags": {
72+
"oneOf": [
73+
{
74+
"$ref": "#/definitions/flagsArray"
75+
},
76+
{
77+
"$ref": "#/definitions/flagsMap"
78+
}
79+
]
80+
}
81+
},
82+
"required": [
83+
"flags"
84+
]
85+
}
86+
]
87+
}
88+
...
89+
```
90+
91+
If the config level flag set ID is not specified, `metadata.flagSetId` of each flag will be interpreted as its flag set ID.
92+
93+
A flag will be uniquely identified by the composite key `(flagKey, flagSetId)`. The following three flags will be considered as three different flags.
94+
95+
1. `{"flagKey": "enable-feature", "flagSetId": ""}`
96+
2. `{"flagKey": "enable-feature", "flagSetId": "default"}`
97+
3. `{"flagKey": "enable-feature", "flagSetId": "beta"}`
98+
99+
### Flagd daemon
100+
101+
Flagd daemon will perform the JSON schema checks with the reference to `https://flagd.dev/schema/v0/flags.json#flagsarray`, allowing both flags as an object and as an array.
102+
103+
If the flag array contains two or more flags with the same composite key, the config will be considered as invalid.
104+
105+
If the request from in-process flagd providers result in a config that has duplicate flag keys, the flagd daemon will only keep one of them in the response.
106+
107+
### Flagd Daemon Storage
108+
109+
1. Flagd will have separate stores for `flags` and `sources`.
110+
111+
1. The `flags` store will use the composite key for flags.
112+
113+
1. `selector` will be removed from the store
114+
115+
1. `flagSetId` will be moved from `source` metadata to `flag` metadata.
116+
117+
### Flags Lifecycle
118+
119+
Currently, the flags configurations from the latest update of a source will trigger a `sync.ALL` sync. If a flag was presented in the previous configuration but not in the current configuration, it will be removed. In another word, the latest source that provides the config for a flag will take the ownership of a flag, and any subsequent configs are considered as the full states of the flags that are owned by the source.
120+
121+
We'll keep the same behaviors with this proposal:
122+
123+
1. If two sources provide the flags with the same composite key, the latest one will be stored.
124+
125+
2. If a flag from a source no longer presents in the latest configuration of the same source, it will be removed.
126+
127+
This behavior is less ideal as the ownership management depends on the ordre of the sync. This should be addressed in a separate ADR.
128+
129+
### Consequences
130+
131+
#### The good
132+
133+
- One source can provide flags with the same keys.
134+
- Flag set ID no longer bound to a source, so one source can have multiple flag sets.
135+
- No breaking change of the API definition and the API behaviors.
136+
- No significant change on the flagd stores and how selections work.
137+
138+
#### The bad
139+
140+
- The proposal still leverages the concept of flag set in the flagd storage.
141+
142+
- The schema does not guarantee that flags of the same flag set from the same source will not have the same keys. This is guaranteed in the proposal of #1634.
143+
144+
- Compared to #1634, this proposal does not allow to define flag set wide metadata.

0 commit comments

Comments
 (0)