fix!: Stop serving payload filters - #867
Merged
Merged
Conversation
keelerm84
force-pushed
the
mk/sdk-3082/remove-payload-filters
branch
2 times, most recently
from
September 11, 2026 18:25
96ed95d to
c7d1d79
Compare
keelerm84
force-pushed
the
mk/sdk-3082/remove-payload-filters
branch
from
September 11, 2026 18:41
c7d1d79 to
0741b79
Compare
keelerm84
marked this pull request as ready for review
September 11, 2026 18:42
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0741b79. Configure here.
The Flag Delivery network does not support payload filters on FDv2. This version of Relay connects only through FDv2, so a configured filter never had any effect: Relay sent ?filter=<key> upstream and the upstream ignored it. Because the option never worked, removing it changes no behavior that anyone could have depended on, and v9 has not had a non-rc release, so the configuration surface can change. Relay created filtered environments on two paths, and both are gone. Manual configuration fanned each environment out once per configured filter key in makeFilteredEnvironments, setting the filter on the copy, appending /<key> to its store prefix, and registering it as <env>/<filterKey>. Config.Filters, FiltersConfig and EnvConfig.FilterKey are removed with it. A [Filters] file section is now rejected as an unknown section, and a LD_FILTER_KEYS_ variable is ignored like any other unrecognized variable. Auto-configuration received filter entities over the RPAC stream and turned each one into an extra environment per filter. The put, patch and delete handling for those entities is removed, along with the filter receiver and the dispatch into the handler. Filter entities now fall through to the same silent branch that the stream already used for unrecognized entities, so LaunchDarkly can keep sending them without a restart or a noisy log. The prefix substitution in envfactory no longer appends a filter key either, which is what made the auto-config path produce the same suffixed prefix as manual configuration. Removing the /<filterKey> prefix on both paths also removes a silent data-loss hazard on Consul, where the filtered view's keys lived under the unfiltered view's subtree and the unfiltered environment's init deleted them. The two /status routes carrying a filter key are removed. Nothing can create a filtered environment for them to report on. The status handler needs no change, because the filter key it reads is simply absent from the remaining routes. The PayloadFilter calls on the data source builders are gone, with the nolint directives that suppressed their deprecation warnings. Documentation for filters is removed rather than rewritten to say the feature is unsupported. The release notes cover the removal. A filter query parameter is accepted and ignored. Authentication no longer reads it, so it cannot affect which environment a request resolves to. The secondary lookup that used to distinguish "credential valid but filter unknown" is gone with it, along with errPayloadFilterNotFound and the 404 it produced. Without this, an SDK that still sends a filter would match no environment and receive 404 on every request. Such an SDK was previously served the environment's full data, because the upstream ignored the filter, so refusing it now would break a client that was working. The filter machinery in projmanager is now unreachable but still present; it comes out in a follow-up along with the remaining types. BREAKING CHANGE: Payload filter support is removed. The [Filters] config section and LD_FILTER_KEYS_ environment variables no longer configure anything, and the two /status routes that took a filter key are gone. The option never had any effect on this version, because the Flag Delivery network does not support payload filters on FDv2. A filter query parameter on a request is accepted and ignored.
keelerm84
force-pushed
the
mk/sdk-3082/remove-payload-filters
branch
from
September 14, 2026 13:34
0741b79 to
77ce3a5
Compare
This was referenced Sep 14, 2026
jsonbailey
approved these changes
Sep 14, 2026
kinyoklion
approved these changes
Sep 14, 2026
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.

Warning
Breaking change. Payload filter support is removed. The
[Filters]config section andLD_FILTER_KEYS_environment variables no longer configure anything, and the two/statusroutes that took a filter key are gone. The option never had any effect on this version, so nothing that worked before stops working. Afilterquery parameter on a request is accepted and ignored.Summary
The Flag Delivery network does not support payload filters on FDv2. This version of Relay connects only through FDv2, so a configured filter never had any effect -- Relay sent
?filter=<key>upstream and the upstream ignored it. Because the option never worked, removing it changes no behavior anyone could have depended on, andv9has had no non-rc release, so the configuration surface is fair game.Relay created filtered environments on two paths, and both are gone.
Manual configuration.
makeFilteredEnvironmentsfanned each environment out once per configured filter key, set the filter on the copy, appended/<key>to its store prefix, and registered it as<env>/<filterKey>. That goes, along withConfig.Filters,FiltersConfigandEnvConfig.FilterKey. A[Filters]file section is now rejected as an unknown section (gcfg does this for free), and aLD_FILTER_KEYS_variable is ignored like any other unrecognized variable. I confirmed both behaviors empirically rather than assuming them.Auto-configuration. LaunchDarkly sends filter entities over the RPAC stream, and Relay turned each into an extra environment per filter. The put, patch and delete handling is removed, along with the filter receiver and the dispatch into the handler. Filter entities now fall through to the branch the stream already had for unrecognized entities -- deliberately a debug log, per its own comment -- so LaunchDarkly can keep sending them with no restart and no log noise. The prefix substitution in
envfactoryno longer appends a filter key either; that was what made this path produce the same suffixed prefix as manual config.The two
/statusroutes carrying a filter key are removed, since nothing can create a filtered environment for them to report on. The status handler needs no change: the filter key it reads is simply absent from the remaining routes.The
PayloadFiltercalls on the data source builders are gone, with thenolintdirectives that suppressed their deprecation warnings (added in #862).A
filterquery parameter is accepted and ignored. Authentication no longer reads it, so it cannot affect which environment a request resolves to. The secondaryUnscope()lookup that distinguished "credential valid but filter unknown" is gone with it, along witherrPayloadFilterNotFound,IsPayloadFilterNotFoundand the 404 they produced.This needed fixing after review: I had claimed the parameter was ignored while authentication still read it, so an SDK sending one got 404 on every request. Cursor Bugbot flagged it and I reproduced it independently. Ignoring is the right behavior rather than rejecting, because such an SDK was already being served the environment's full data (the upstream ignores the filter on FDv2), so refusing it now would break a client that was working.
Filter documentation is removed rather than rewritten to say the feature is unsupported; the release notes cover the removal. That includes the
[Filters "PROJECT-KEY"]section inconfiguration.md, the filtered status routes and their examples inendpoints.md, and the" (<filterKey>)"display-name clause. No dangling links remain --endpoints.mdhad linked to theconfiguration.md#payload-filteringanchor.Side effect worth having
Removing the
/<filterKey>prefix on both paths removes a silent data-loss hazard on Consul. A filtered view's keys lived under the unfiltered view's subtree, because the separator is/and Consul treats that as a path separator.go-server-sdk-consul'sInitdoeskv.List(prefix)and deletes every key not in the payload it writes, so the unfiltered environment's init deleted the filtered view's flags and its$initedsentinel with nothing logged. Fixing only the manual path would have left this live under auto-config. The hazard remains onv8, where FDv1 filtering genuinely works, and needs its own ticket.Tests
Tests covering the removed behavior are replaced by tests covering the new behavior:
TestFilterEventsAreIgnoredpins the RPAC contract: a filter patch, a filter delete and a malformed filter patch each reach no handler and cause no restart. Because "nothing happened" would also hold for a dead stream, each case then sends an environment patch and requires it through, proving the connection survived.TestNewRelayDoesNotCreateFilteredEnvironmentsasserts the environment set matches the declared configuration.TestStrayFilterQueryParameterIsIgnoredsends the same request with and without?filter=, requires 200 for both, and compares the set of objects returned. It compares object sets rather than raw bytes becauseserializeBasisV2walks a map of data kinds, so Go randomizes flag-versus-segment ordering; a byte comparison passed in isolation then failed in the full suite. I confirmed it fails when the query-parameter lookup is restored.buildPreRoutedRequestWithFilterandreturns 404 if key is correct but filter is unrecognized. Two of them hung rather than failed once the lookup stopped matching, because they block on a channel the handler never reaches.TestWellFormedJSONThatIsNotWellFormedEventDataCausesStreamRestart/patch/filtersis removed. It asserted a malformed filter patch restarts the stream; a filter path is now an unrecognized entity, so it is ignored instead. That is the intended consequence, not a regression./status/{projKey}/{envKey}, so the case survives without referencing a dead route.TestMakeFilteredEnvironments_*, the threeTestNewRelayDisallowsFilters*,TestFilterPutEvent/TestFilterPatchEvent/TestFilterDeleteEvent, and the filtered-status 404 subtest.Net: 578 deletions against 54 insertions.
Follow-ups
The filter machinery in
projmanager(AddFilter,DeleteFilter, thefilteredmap) is now unreachable but still compiled; it comes out next along withinternal/sdkauth, which exists solely because of payload filtering, and finallyconfig.FilterKey/FilterID/DefaultFilteronce nothing references them.Note
Overview
Breaking change: Payload filtering is removed end-to-end. The
[Filters]config section,LD_FILTER_KEYS_*env vars, filtered environment fan-out, auto-config filter stream handling,/status/.../filters/{filterKey}routes, and SDKPayloadFilterwiring are all gone.Relay now registers only environments declared in config (or from auto-config environments), without
<env>/<filterKey>copies or filter-key suffixes on datastore prefixes. Auto-config filter SSE events are treated like unknown entities (debug log, no handler, no stream restart) so upstream can keep sending them quietly.Client behavior: The
filterquery parameter is ignored—requests still authenticate and receive the full environment payload instead of 404. Middleware and relay no longer exposeIsPayloadFilterNotFound.Docs drop the Filters section, filtered status examples, and filter-related display-name notes. Tests replace filter-specific coverage with checks that filter events are ignored, filtered envs are not created, and
?filter=returns the same data as unfiltered poll.Reviewed by Cursor Bugbot for commit 77ce3a5. Bugbot is set up for automated code reviews on this repo. Configure here.