Skip to content

fix(flags): only install HyperCacheFlagProvider in US#56768

Closed
sampennington wants to merge 3 commits into
masterfrom
fix/feature-flags-hypercache-us-only
Closed

fix(flags): only install HyperCacheFlagProvider in US#56768
sampennington wants to merge 3 commits into
masterfrom
fix/feature-flags-hypercache-us-only

Conversation

@sampennington

@sampennington sampennington commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Problem

Local feature-flag evaluation in our server-side posthoganalytics SDK returns None instead of True/False in EU pods (works in US). Customer-facing example: posthoganalytics.feature_enabled("persons-on-events-v2-reads-enabled", ..., only_evaluate_locally=True) finds no flag definition.

apps.py keys HyperCacheFlagProvider by team_id=2 (no env override is set anywhere), assuming "local team 2 == PostHog company project". That holds in US Postgres, not in EU. The provider also returns a truthy dict for an empty flags list, so the SDK accepts the EU cache as authoritative and never falls back to its API path.

Changes

Gate provider install on settings.CLOUD_DEPLOYMENT == "US". Outside US, leave flag_definition_cache_provider unset so the SDK polls posthoganalytics.host (us.i.posthog.com) directly — the cross-region behavior that worked before #50737. Gate lives in a small get_default_flag_definition_cache_provider() helper in sdk_cache_provider.py so it's testable without invoking AppConfig.ready().

How did you test this code?

I'm an agent (PostHog Code). Added TestGetDefaultFlagDefinitionCacheProvider parameterized over US / EU / DEV / E2E / LOCAL / unset, with and without POSTHOG_SELF_TEAM_ID override (8 cases). Existing tests untouched. Did not run the full pytest suite — sandbox lacked the flox venv. Verified ruff check clean and smoke-tested the helper against all 8 cases.

Publish to changelog?

no

🤖 Agent context

  • Authored by PostHog Code (Claude). Human review required.
  • Diagnosis: apps.py:79-88, sdk_cache_provider.py:43-68, and posthoganalytics 7.13.0::client.py::_load_feature_flags (lines 1253-1296 — the truthy-payload-accepted-as-authoritative path).
  • Deviation from the originating prompt: the gate was extracted into a small factory rather than placed inline in apps.py, because AppConfig.ready() forces posthoganalytics.disabled=True in TEST mode and runs many other side effects, making a true regression test fragile. The factory captures the same semantic gate and is directly testable.
  • Reviewer should sanity-check that EU Postgres team 2 isn't the company project (the fix doesn't depend on which team it is, only that it's not the company project — but worth confirming).
  • Follow-ups (not in this PR): metric/log when get_flag_definitions() returns empty flags; CLOUD_DEPLOYMENT in {"US"} allowlist constant for future US-WEST style splits.

The provider is keyed by team_id (defaults to 2), which only refers to the
PostHog company project in US Postgres. In EU and other regions team 2 is
an unrelated org, so the SDK reads the wrong flag definitions and local
evaluation of company flags returns None.

Compounding the issue, the provider always returns a truthy dict (even for
an empty flags list), which the SDK accepts as authoritative — so the
emergency API fallback never fires and the bad cache state sticks until
restart.

Gate the provider installation on CLOUD_DEPLOYMENT == "US". Outside US,
leave flag_definition_cache_provider unset so the SDK falls back to its
normal API polling against posthoganalytics.host (us.i.posthog.com), which
is the cross-region behavior that worked before #50737.

Generated-By: PostHog Code
Task-Id: 2dfd1690-4890-4d79-b62e-167289f38dca
@greptile-apps

greptile-apps Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
This is a comment left during a code review.
Path: posthog/feature_flags/test_sdk_cache_provider.py
Line: 227-250

Comment:
**Non-parameterized US and EU override tests**

The four test methods in this class test the same function with varying `(CLOUD_DEPLOYMENT, POSTHOG_SELF_TEAM_ID, expected_result)` combinations. Per the project's preference for parameterised tests, these could be consolidated into a single `@parameterized.expand` case list, eliminating the repeated `setUp`/`tearDown` env-isolation boilerplate and making it trivial to add new regions or env-var combinations:

```python
@parameterized.expand([
    ("us_default",         "US",   None,  2),
    ("us_env_override",    "US",   "42",  42),
    ("eu_no_env",          "EU",   None,  None),
    ("eu_env_override",    "EU",   "42",  None),
    ("dev",                "DEV",  None,  None),
    ("e2e",                "E2E",  None,  None),
    ("none",               None,   None,  None),
])
@patch.dict(os.environ, {}, clear=False)
def test_provider(self, _name, deployment, env_team_id, expected_team_id):
    if env_team_id is not None:
        os.environ["POSTHOG_SELF_TEAM_ID"] = env_team_id
    else:
        os.environ.pop("POSTHOG_SELF_TEAM_ID", None)
    with override_settings(CLOUD_DEPLOYMENT=deployment):
        provider = get_default_flag_definition_cache_provider()
    if expected_team_id is None:
        assert provider is None
    else:
        assert isinstance(provider, HyperCacheFlagProvider)
        assert provider._team_id == expected_team_id
```

This covers all seven current cases in one place and makes the separate `setUp`/`tearDown` unnecessary.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(flags): only install HyperCacheFlagP..." | Re-trigger Greptile

Comment thread posthog/feature_flags/test_sdk_cache_provider.py Outdated
Consolidate the four region/env-override test methods into a single
parameterized test_provider, per AGENTS.md preference for parameterized
tests. Drops the setUp/tearDown env-isolation boilerplate in favor of a
@patch.dict(os.environ, {}, clear=False) decorator at the method level.

Generated-By: PostHog Code
Task-Id: 2dfd1690-4890-4d79-b62e-167289f38dca
- Add LOCAL row to parameterized test (documented CLOUD_DEPLOYMENT value).
- Drop test class docstring per AGENTS.md ("Python tests: do not add doc
  comments").
- Rewrite env handling declaratively: each row carries an env_overrides
  dict and the test uses patch.dict(..., clear=True) for per-row isolation
  instead of mutating os.environ inside the test body.
- Restore the E2E cold-cache note in apps.py.

Generated-By: PostHog Code
Task-Id: 2dfd1690-4890-4d79-b62e-167289f38dca
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant