diff --git a/.changeset/adapter-bulk-evaluation.md b/.changeset/adapter-bulk-evaluation.md deleted file mode 100644 index 135ffc64..00000000 --- a/.changeset/adapter-bulk-evaluation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@flags-sdk/vercel': minor ---- - -Reduces overhead when evaluating multiple flags via `evaluate()` or `precompute()` by using new bulk evaluation capabilities of `@vercel/flags-core`. diff --git a/.changeset/core-bulk-evaluation.md b/.changeset/core-bulk-evaluation.md deleted file mode 100644 index 00674913..00000000 --- a/.changeset/core-bulk-evaluation.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@vercel/flags-core': minor ---- - -Add `bulkEvaluate` method to `FlagsClient` for resolving multiple flags against shared entities in a single call. - -```ts -const results = await client.bulkEvaluate( - [ - { key: 'a', defaultValue: false }, - { key: 'b', defaultValue: 'off' }, - ], - entities, -); - -results.a; // EvaluationResult -results.b; // EvaluationResult -``` - -Avoids the per-flag overhead of separate `evaluate()` calls — the datafile is read once, entities are resolved once, and all flags share the same environment/segments lookup. Each entry in the returned record is a full `EvaluationResult` with `value`, `reason`, `outcomeType`, and `metrics`. diff --git a/.changeset/evaluate-perf-improvements.md b/.changeset/evaluate-perf-improvements.md deleted file mode 100644 index bddcdd05..00000000 --- a/.changeset/evaluate-perf-improvements.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@vercel/flags-core': patch ---- - -Speed up flag evaluation on the hot path. - -- `handleOutcome` no longer recomputes `scaledWeights` on every split-outcome evaluation; the per-outcome scaled weights are cached on first call. -- `matchConditions` no longer recompiles `RegExp` on every REGEX / NOT_REGEX condition; the compiled regex is cached on first call. -- `Controller.read()` and `getDatafile()` no longer re-destructure and re-spread the in-memory datafile on every call; the result is cached and rebuilt only when stream/poll replaces the underlying data. - -In micro-benchmarks the pure `evaluate()` path is ~22% faster for split outcomes and ~32% faster for regex conditions. The full `client.evaluate()` path is 14–22% faster across all scenarios. diff --git a/.changeset/flags-evaluate.md b/.changeset/flags-evaluate.md deleted file mode 100644 index 07304c42..00000000 --- a/.changeset/flags-evaluate.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'flags': minor ---- - -When applications call `evaluate()` or `precompute()` function from `flags/next` it now defers bulk evaluation to the underlying adapters in case those support it, or otherwise falls back to evaluating each flag individually. - -This speeds up evaluation for applications that need to evaluate multiple flags at once, as the runtime needs to handle fewer promises and more work is reused. In testing we have seen a 20x improvement when called with 100 flags. - -```tsx -import { evaluate } from 'flags/next'; -import { flagA, flagB } from '../flags'; - -// pass a list of flags -const [valueA, valueB] = await evaluate([flagA, flagB]); - -// pass an object -const { a, b } = await evaluate({ a: flagA, b: flagB }); -``` - -Adapters can opt into bulk evaluation by implementing a `bulkDecide` method and setting a stable `adapterId`. When both are present, flag evaluation groups flags that share the same `adapterId` and `identify` source and invokes `bulkDecide` once per group instead of calling `decide` per flag. Flags without a bulk-capable adapter still resolve through the normal per-flag path inside `evaluate()` and still benefit from now reusing the shared per-request headers, cookies, and overrides reads. - -Tracing reflects this grouping. `evaluate()` (and therefore `precompute()`) now emits an `evaluate` span carrying a `flagCount` attribute. Within it, bulk-evaluated flags no longer emit an individual per-flag `run` span; instead each adapter group emits a single `batch` span (carrying the `adapterId`, the `keys` evaluated in the batch, and `cachedCount`/`overrideCount`/`decidedCount` attributes summarizing how the batch resolved) so per-flag instrumentation overhead is not reintroduced. Flags that fall back to the per-flag path continue to emit their own `flag` span as before. diff --git a/.changeset/jitter-ingest-retries.md b/.changeset/jitter-ingest-retries.md deleted file mode 100644 index ef5ae3b0..00000000 --- a/.changeset/jitter-ingest-retries.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@vercel/flags-core': minor ---- - -Add jitter to ingest retries and the batch-flush window. - -The usage tracker now uses AWS-style "Full Jitter" exponential backoff between -retry attempts (replacing the previous deterministic 100/200ms schedule) and -randomizes the 5s batch-flush window by ±20% to desynchronize concurrent -processes. When all retry attempts are exhausted the SDK now logs a structured -warning so consumers can alert on dropped batches. diff --git a/.changeset/twelve-shoes-behave.md b/.changeset/twelve-shoes-behave.md deleted file mode 100644 index 4dbe53f8..00000000 --- a/.changeset/twelve-shoes-behave.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@flags-sdk/vercel": minor -"@vercel/prepare-flags-definitions": minor -"@vercel/flags-core": minor ---- - -Add OIDC authentication support for Vercel Flags clients and generated flag definitions. - -`@vercel/flags-core` can now create clients without an SDK key and authenticate with a Vercel OIDC token, while still supporting SDK keys and connection strings. Bundled definitions can be looked up by SDK key hash or OIDC project ID. - -`@vercel/prepare-flags-definitions` now collects both SDK keys and `VERCEL_OIDC_TOKEN`, fetches definitions for each auth entry, deduplicates identical definitions across SDK keys and OIDC project IDs, and writes generated maps keyed by SDK key hash or project ID. - -`@flags-sdk/vercel` now supports provider data lookup for Vercel flag origins that do not include an SDK key, allowing OIDC-backed clients to resolve project metadata. diff --git a/packages/adapter-vercel/CHANGELOG.md b/packages/adapter-vercel/CHANGELOG.md index e4ba8c4c..4b5c7b01 100644 --- a/packages/adapter-vercel/CHANGELOG.md +++ b/packages/adapter-vercel/CHANGELOG.md @@ -1,5 +1,24 @@ # @flags-sdk/vercel +## 1.4.0 + +### Minor Changes + +- [#385](https://github.com/vercel/flags/pull/385) [`201f9d5`](https://github.com/vercel/flags/commit/201f9d5988d7fc307511e35638e66769d38cedb3) Thanks [@dferber90](https://github.com/dferber90)! - Reduces overhead when evaluating multiple flags via `evaluate()` or `precompute()` by using new bulk evaluation capabilities of `@vercel/flags-core`. + +- [#390](https://github.com/vercel/flags/pull/390) [`7b5ea9a`](https://github.com/vercel/flags/commit/7b5ea9a808dfd4155bd2bbf321c3b44ec730cda6) Thanks [@luismeyer](https://github.com/luismeyer)! - Add OIDC authentication support for Vercel Flags clients and generated flag definitions. + + `@vercel/flags-core` can now create clients without an SDK key and authenticate with a Vercel OIDC token, while still supporting SDK keys and connection strings. Bundled definitions can be looked up by SDK key hash or OIDC project ID. + + `@vercel/prepare-flags-definitions` now collects both SDK keys and `VERCEL_OIDC_TOKEN`, fetches definitions for each auth entry, deduplicates identical definitions across SDK keys and OIDC project IDs, and writes generated maps keyed by SDK key hash or project ID. + + `@flags-sdk/vercel` now supports provider data lookup for Vercel flag origins that do not include an SDK key, allowing OIDC-backed clients to resolve project metadata. + +### Patch Changes + +- Updated dependencies [[`201f9d5`](https://github.com/vercel/flags/commit/201f9d5988d7fc307511e35638e66769d38cedb3), [`4d90e91`](https://github.com/vercel/flags/commit/4d90e912a4d7c9d4ef986d5e8dc609c30b203242), [`bd4d01a`](https://github.com/vercel/flags/commit/bd4d01a9b2b5d70bf7ae62cda645d8cd7292ad83), [`7b5ea9a`](https://github.com/vercel/flags/commit/7b5ea9a808dfd4155bd2bbf321c3b44ec730cda6)]: + - @vercel/flags-core@1.5.0 + ## 1.3.0 ### Minor Changes diff --git a/packages/adapter-vercel/package.json b/packages/adapter-vercel/package.json index de583dc4..3cc13440 100644 --- a/packages/adapter-vercel/package.json +++ b/packages/adapter-vercel/package.json @@ -1,6 +1,6 @@ { "name": "@flags-sdk/vercel", - "version": "1.3.0", + "version": "1.4.0", "description": "A Flags SDK adapter for Vercel Flags", "keywords": [ "vercel", diff --git a/packages/flags/CHANGELOG.md b/packages/flags/CHANGELOG.md index 8f15cf2f..1bcb707d 100644 --- a/packages/flags/CHANGELOG.md +++ b/packages/flags/CHANGELOG.md @@ -1,5 +1,28 @@ # @vercel/flags +## 4.1.0 + +### Minor Changes + +- [#385](https://github.com/vercel/flags/pull/385) [`201f9d5`](https://github.com/vercel/flags/commit/201f9d5988d7fc307511e35638e66769d38cedb3) Thanks [@dferber90](https://github.com/dferber90)! - When applications call `evaluate()` or `precompute()` function from `flags/next` it now defers bulk evaluation to the underlying adapters in case those support it, or otherwise falls back to evaluating each flag individually. + + This speeds up evaluation for applications that need to evaluate multiple flags at once, as the runtime needs to handle fewer promises and more work is reused. In testing we have seen a 20x improvement when called with 100 flags. + + ```tsx + import { evaluate } from "flags/next"; + import { flagA, flagB } from "../flags"; + + // pass a list of flags + const [valueA, valueB] = await evaluate([flagA, flagB]); + + // pass an object + const { a, b } = await evaluate({ a: flagA, b: flagB }); + ``` + + Adapters can opt into bulk evaluation by implementing a `bulkDecide` method and setting a stable `adapterId`. When both are present, flag evaluation groups flags that share the same `adapterId` and `identify` source and invokes `bulkDecide` once per group instead of calling `decide` per flag. Flags without a bulk-capable adapter still resolve through the normal per-flag path inside `evaluate()` and still benefit from now reusing the shared per-request headers, cookies, and overrides reads. + + Tracing reflects this grouping. `evaluate()` (and therefore `precompute()`) now emits an `evaluate` span carrying a `flagCount` attribute. Within it, bulk-evaluated flags no longer emit an individual per-flag `run` span; instead each adapter group emits a single `batch` span (carrying the `adapterId`, the `keys` evaluated in the batch, and `cachedCount`/`overrideCount`/`decidedCount` attributes summarizing how the batch resolved) so per-flag instrumentation overhead is not reintroduced. Flags that fall back to the per-flag path continue to emit their own `flag` span as before. + ## 4.0.6 ### Patch Changes diff --git a/packages/flags/package.json b/packages/flags/package.json index b6982a56..3f3113f2 100644 --- a/packages/flags/package.json +++ b/packages/flags/package.json @@ -1,6 +1,6 @@ { "name": "flags", - "version": "4.0.6", + "version": "4.1.0", "description": "Flags SDK by Vercel - The feature flags toolkit for Next.js and SvelteKit", "keywords": [ "feature flags", diff --git a/packages/prepare-flags-definitions/CHANGELOG.md b/packages/prepare-flags-definitions/CHANGELOG.md index 1c7c9043..3edc1028 100644 --- a/packages/prepare-flags-definitions/CHANGELOG.md +++ b/packages/prepare-flags-definitions/CHANGELOG.md @@ -1,5 +1,17 @@ # @vercel/prepare-flags-definitions +## 0.3.0 + +### Minor Changes + +- [#390](https://github.com/vercel/flags/pull/390) [`7b5ea9a`](https://github.com/vercel/flags/commit/7b5ea9a808dfd4155bd2bbf321c3b44ec730cda6) Thanks [@luismeyer](https://github.com/luismeyer)! - Add OIDC authentication support for Vercel Flags clients and generated flag definitions. + + `@vercel/flags-core` can now create clients without an SDK key and authenticate with a Vercel OIDC token, while still supporting SDK keys and connection strings. Bundled definitions can be looked up by SDK key hash or OIDC project ID. + + `@vercel/prepare-flags-definitions` now collects both SDK keys and `VERCEL_OIDC_TOKEN`, fetches definitions for each auth entry, deduplicates identical definitions across SDK keys and OIDC project IDs, and writes generated maps keyed by SDK key hash or project ID. + + `@flags-sdk/vercel` now supports provider data lookup for Vercel flag origins that do not include an SDK key, allowing OIDC-backed clients to resolve project metadata. + ## 0.2.1 ### Patch Changes diff --git a/packages/prepare-flags-definitions/package.json b/packages/prepare-flags-definitions/package.json index 7b6bc95c..cea8630b 100644 --- a/packages/prepare-flags-definitions/package.json +++ b/packages/prepare-flags-definitions/package.json @@ -1,6 +1,6 @@ { "name": "@vercel/prepare-flags-definitions", - "version": "0.2.1", + "version": "0.3.0", "description": "A utility for preparing flags definitions for embedding", "keywords": [ "flags", diff --git a/packages/vercel-flags-core/CHANGELOG.md b/packages/vercel-flags-core/CHANGELOG.md index 01078c60..f81f4539 100644 --- a/packages/vercel-flags-core/CHANGELOG.md +++ b/packages/vercel-flags-core/CHANGELOG.md @@ -1,5 +1,52 @@ # @vercel/flags-core +## 1.5.0 + +### Minor Changes + +- [#385](https://github.com/vercel/flags/pull/385) [`201f9d5`](https://github.com/vercel/flags/commit/201f9d5988d7fc307511e35638e66769d38cedb3) Thanks [@dferber90](https://github.com/dferber90)! - Add `bulkEvaluate` method to `FlagsClient` for resolving multiple flags against shared entities in a single call. + + ```ts + const results = await client.bulkEvaluate( + [ + { key: "a", defaultValue: false }, + { key: "b", defaultValue: "off" }, + ], + entities + ); + + results.a; // EvaluationResult + results.b; // EvaluationResult + ``` + + Avoids the per-flag overhead of separate `evaluate()` calls — the datafile is read once, entities are resolved once, and all flags share the same environment/segments lookup. Each entry in the returned record is a full `EvaluationResult` with `value`, `reason`, `outcomeType`, and `metrics`. + +- [#371](https://github.com/vercel/flags/pull/371) [`bd4d01a`](https://github.com/vercel/flags/commit/bd4d01a9b2b5d70bf7ae62cda645d8cd7292ad83) Thanks [@vincent-derks](https://github.com/vincent-derks)! - Add jitter to ingest retries and the batch-flush window. + + The usage tracker now uses AWS-style "Full Jitter" exponential backoff between + retry attempts (replacing the previous deterministic 100/200ms schedule) and + randomizes the 5s batch-flush window by ±20% to desynchronize concurrent + processes. When all retry attempts are exhausted the SDK now logs a structured + warning so consumers can alert on dropped batches. + +- [#390](https://github.com/vercel/flags/pull/390) [`7b5ea9a`](https://github.com/vercel/flags/commit/7b5ea9a808dfd4155bd2bbf321c3b44ec730cda6) Thanks [@luismeyer](https://github.com/luismeyer)! - Add OIDC authentication support for Vercel Flags clients and generated flag definitions. + + `@vercel/flags-core` can now create clients without an SDK key and authenticate with a Vercel OIDC token, while still supporting SDK keys and connection strings. Bundled definitions can be looked up by SDK key hash or OIDC project ID. + + `@vercel/prepare-flags-definitions` now collects both SDK keys and `VERCEL_OIDC_TOKEN`, fetches definitions for each auth entry, deduplicates identical definitions across SDK keys and OIDC project IDs, and writes generated maps keyed by SDK key hash or project ID. + + `@flags-sdk/vercel` now supports provider data lookup for Vercel flag origins that do not include an SDK key, allowing OIDC-backed clients to resolve project metadata. + +### Patch Changes + +- [#382](https://github.com/vercel/flags/pull/382) [`4d90e91`](https://github.com/vercel/flags/commit/4d90e912a4d7c9d4ef986d5e8dc609c30b203242) Thanks [@dferber90](https://github.com/dferber90)! - Speed up flag evaluation on the hot path. + + - `handleOutcome` no longer recomputes `scaledWeights` on every split-outcome evaluation; the per-outcome scaled weights are cached on first call. + - `matchConditions` no longer recompiles `RegExp` on every REGEX / NOT_REGEX condition; the compiled regex is cached on first call. + - `Controller.read()` and `getDatafile()` no longer re-destructure and re-spread the in-memory datafile on every call; the result is cached and rebuilt only when stream/poll replaces the underlying data. + + In micro-benchmarks the pure `evaluate()` path is ~22% faster for split outcomes and ~32% faster for regex conditions. The full `client.evaluate()` path is 14–22% faster across all scenarios. + ## 1.4.0 ### Minor Changes diff --git a/packages/vercel-flags-core/package.json b/packages/vercel-flags-core/package.json index b026ac9a..172f5223 100644 --- a/packages/vercel-flags-core/package.json +++ b/packages/vercel-flags-core/package.json @@ -1,6 +1,6 @@ { "name": "@vercel/flags-core", - "version": "1.4.0", + "version": "1.5.0", "description": "A server-side client for Vercel Flags", "keywords": [ "vercel",