feat(flags-core): read client config (disableMetrics) from datafile#425
Draft
luismeyer wants to merge 1 commit into
Draft
feat(flags-core): read client config (disableMetrics) from datafile#425luismeyer wants to merge 1 commit into
luismeyer wants to merge 1 commit into
Conversation
The flags server can now deliver an optional top-level `config` field in
the datafile payload:
{ "config": { "disableMetrics": true } }
Since all sources (stream, poll, bundled, provided datafile, one-time
fetch) emit raw DatafileInput, the config flows through every source
automatically. The Controller reads it from the latest known data, so
config updates arriving at runtime take effect for subsequent tracking.
When the latest datafile sets config.disableMetrics: true, no usage
metrics are ingested: trackRead/trackEvaluation are gated in the
Controller, and the UsageTracker additionally consults an isDisabled
predicate before recording and before flushing (pending events are
dropped instead of sent, so flushes never hit the network).
Absent config means all defaults — behavior unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
dferber90
reviewed
Jul 9, 2026
| * runtime (e.g. a stream update) takes effect for subsequent tracking. | ||
| */ | ||
| private get metricsDisabledByConfig(): boolean { | ||
| return this.data?.config?.disableMetrics === true; |
Collaborator
There was a problem hiding this comment.
small fly-by nitpick: It's usually more future-proof to use an enum, just in case there are other modes in the future.
metrics: false can more easily turn into metrics: "config-reads-only" or any other modes we might want
so I'd keep "disable" out of the config name
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Teaches
@vercel/flags-coreto read client configuration delivered by the flags server via the datafile payload, and uses it to control client behavior. The first config option isdisableMetrics: when the server sends it, the client never ingests any usage metrics.This is the client half of a two-part feature; the server half (vercel/proxy) sends the field. Agreed protocol:
{ "config": { "disableMetrics": true } }configis an optional top-level datafile field; absent means all defaults (metrics enabled)config.disableMetricsis an optional boolean, defaultfalseClientConfigshape is extensible for future optionsDesign
Parsing —
ClientConfigis typed onDatafileInput(src/types.ts). Since all sources (stream, polling, bundled definitions, provided datafile, one-time fetch) emit rawDatafileInputparsed from the same JSON payload, the config flows through every source with no per-source changes.ClientConfigis exported from the public entry point.Gating — the Controller owns the latest tagged data, so it exposes a private
metricsDisabledByConfiggetter readingthis.data?.config?.disableMetrics. Because it always reads the latest known data, a config flip arriving at runtime (e.g. a stream update) takes effect for subsequent tracking immediately.Metrics are suppressed at two layers:
Controller.trackRead/Controller.trackEvaluationreturn early while disabled — no events accumulateUsageTrackertakes anisDisabledpredicate consulted before recording and before flushing: while disabled, pending events are dropped instead of sent, so flushes never hit the network (covers events queued before a runtime flip)Controller.shutdown()now flushes the tracker before resettingthis.data, so the final flush still sees the latest config.The existing local
disableMetricsconstructor option (client-side, evaluation metrics only) is unchanged; the server-driven config gates all metrics.Tests
New black-box tests (through
createClient,fetchMockfor network assertions):config.disableMetrics: true→ zero ingest requests (evaluation still works)configpresent but nodisableMetrics→ ingest body byte-identical to current behaviordisableMetricson → subsequent tracking stops, pending events dropped, no ingest request everdisableMetricsoff → tracking resumes; ingest contains only post-flip eventsconfig.disableMetrics: true(build step) → zero ingest requestspnpm test(472 passed),pnpm type-check,pnpm check(biome), andpnpm buildall pass inpackages/vercel-flags-core.🤖 Generated with Claude Code