Skip to content

feat: add evaluate_flags/2 API for single-call flag evaluation#103

Open
dmarticus wants to merge 1 commit intomainfrom
posthog-code/elixir-evaluate-flags-api
Open

feat: add evaluate_flags/2 API for single-call flag evaluation#103
dmarticus wants to merge 1 commit intomainfrom
posthog-code/elixir-evaluate-flags-api

Conversation

@dmarticus
Copy link
Copy Markdown
Contributor

@dmarticus dmarticus commented Apr 27, 2026

Summary

  • New PostHog.FeatureFlags.evaluate_flags/2 returns an Evaluations snapshot from a single /flags call.
  • Snapshot exposes enabled?/2, get_flag/2, get_flag_payload/2, only/2, keys/1, event_properties/1. enabled?/2 and get_flag/2 fire $feature_flag_called with full metadata; get_flag_payload/2 doesn't.
  • set_in_context/2 copies the snapshot's $feature/<key> and $active_feature_flags into the per-process context so subsequent PostHog.capture/3 calls pick them up — no new capture arity needed.
  • %PostHog.FeatureFlags.Result{} now carries :id, :version, :reason, :request_id, and :evaluated_at. The existing check/3, check!/3, and get_feature_flag_result/4 paths attach the matching $feature_flag_* properties to $feature_flag_called events when the response provides them — needed for experiment exposure tracking.
  • Pass flag_keys: [...] to evaluate_flags/2 to scope the underlying /flags request itself (forwarded as flag_keys_to_evaluate).

RFC: https://github.com/PostHog/requests-for-comments-internal/pull/1020. Reference implementations: posthog-python#539, posthog-js#3476.

Design decisions

  • No capture(flags: snapshot) argument. Elixir's SDK already propagates $feature/* through the per-process context that check/3 writes to and capture/3 reads back. set_in_context/2 slots into that mechanism instead of fighting it.
  • Snapshot is pure-functional, not Agent-backed. Mutable access tracking would require an Agent or threading a new snapshot through every query — both awkward in Elixir. only/2 (filter by explicit keys) is enough; only_accessed/1 from the cross-SDK API is dropped.
  • Predicate is enabled?/2, not is_enabled/2. Idiomatic Elixir; is_* is reserved for guard-safe predicates and Credo flags it.
  • Both paths share build_result/3 and log_feature_flag_usage/3. The existing single-flag path now emits the same rich metadata as the new snapshot path — single source of truth for $feature_flag_called properties.
  • No dedup cache. The Elixir SDK has no per-distinct_id dedup for $feature_flag_called; both paths fire on every access. Adding the cache is a separate behavior change to existing call sites and lands in its own PR.
  • No new config option. only/2 silently drops unknown keys (matching Map.take/2), so there's no warning to silence.

Phase 2 follow-ups

  • Per-distinct_id dedup cache for $feature_flag_called events, applied to both paths.
  • Local-evaluation poller, with locally_evaluated, $feature_flag_reason: "Evaluated locally", and $feature_flag_definitions_loaded_at plumbed through the snapshot.
  • Runtime deprecation warnings on check/3, check!/3, get_feature_flag_result/4, get_feature_flag_result!/4 pointing at evaluate_flags/2.
  • only_accessed/1 if users ask for it.

Created with PostHog Code

Introduce PostHog.FeatureFlags.evaluate_flags/2 returning an Evaluations
snapshot that powers branching across multiple flags and event enrichment
from a single /flags request. Pairs with PostHog.FeatureFlags.set_in_context/2
for the idiomatic Elixir capture-enrichment flow via the existing per-process
context, and with Evaluations.event_properties/1 for explicit one-off attach.

%PostHog.FeatureFlags.Result{} gains :id, :version, :reason, :request_id, and
:evaluated_at. The existing check/3, check!/3, and get_feature_flag_result/4
paths now attach $feature_flag_id, $feature_flag_version, $feature_flag_reason,
and $feature_flag_request_id to $feature_flag_called events when the response
provides them - needed for experiment exposure tracking.

Generated-By: PostHog Code
Task-Id: c6aa804c-618a-4229-b6a3-dc8c9ccff778
@github-actions
Copy link
Copy Markdown
Contributor

posthog-elixir Compliance Report

Date: 2026-04-27 20:20:45 UTC
Duration: 207ms

⚠️ Some Tests Failed

0/1 tests passed, 1 failed


Feature_Flags Tests

⚠️ 0/1 tests passed, 1 failed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 6ms

Failures

request_payload.request_with_person_properties_device_id

404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'

@dmarticus dmarticus marked this pull request as ready for review April 27, 2026 22:12
@dmarticus dmarticus requested review from a team and rafaeelaudibert as code owners April 27, 2026 22:12
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