PostHog.FeatureFlags.Evaluations (posthog v2.8.2)

View Source

Snapshot of feature flag evaluations for a single distinct_id.

An Evaluations struct represents the result of a single /flags call. It is built by PostHog.FeatureFlags.evaluate_flags/2 and lets you branch on multiple flags and enrich captured events from the same fetch — without paying the cost of one round-trip per flag.

Each snapshot owns a small Agent linked to the calling process that tracks which flags were accessed via enabled?/2 and get_flag/2. The Agent exits with the calling process — no manual cleanup is required.

Querying

Use enabled?/2, get_flag/2, and get_flag_payload/2 to read individual flags. enabled?/2 and get_flag/2 record access and fire a $feature_flag_called event with full metadata (id, version, reason, request_id) on each call; get_flag_payload/2 does neither.

{:ok, snapshot} = PostHog.FeatureFlags.evaluate_flags("user-123")

if PostHog.FeatureFlags.Evaluations.enabled?(snapshot, "new-dashboard") do
  render_new_dashboard()
end

Enriching captures

Call PostHog.FeatureFlags.set_in_context/2 to copy the snapshot's $feature/<key> and $active_feature_flags properties into the per-process context. Any subsequent PostHog.capture/3 automatically picks them up — no additional /flags request, and the values match what you branched on.

PostHog.FeatureFlags.set_in_context(snapshot)
PostHog.capture("page_viewed", %{distinct_id: "user-123"})

Or merge event_properties/1 directly into a capture's properties for an explicit, one-off attach without touching context.

Filtering

Use only_accessed/1 to narrow a snapshot to flags accessed so far via enabled?/2 or get_flag/2. Use only/2 to narrow by an explicit key list. Both return a fresh snapshot with its own access tracker — calls on the filtered view do not back-propagate to the parent.

narrowed = PostHog.FeatureFlags.Evaluations.only_accessed(snapshot)
PostHog.FeatureFlags.set_in_context(narrowed)

Summary

Types

t()

Snapshot of evaluated flags for a single distinct_id.

Functions

Returns the sorted list of keys accessed via enabled?/2 or get_flag/2 on this snapshot.

Returns whether the named flag is enabled in this snapshot.

Returns the $feature/<key> and $active_feature_flags properties for this snapshot, suitable for merging into a captured event's properties.

Returns the variant string, the enabled boolean, or nil for unknown flags.

Returns the configured payload for the flag, or nil for unknown flags or flags without a payload.

Returns the sorted list of flag keys present in the snapshot.

Returns a copy of the snapshot scoped to the given keys. Unknown keys are silently dropped.

Returns a copy of the snapshot scoped to the flags accessed so far via enabled?/2 or get_flag/2.

Types

t()

@type t() :: %PostHog.FeatureFlags.Evaluations{
  accessed_pid: pid(),
  distinct_id: PostHog.distinct_id(),
  errors_while_computing: boolean(),
  evaluated_at: integer() | nil,
  flags: %{required(String.t()) => PostHog.FeatureFlags.Result.t()},
  request_id: String.t() | nil,
  supervisor_name: PostHog.supervisor_name()
}

Snapshot of evaluated flags for a single distinct_id.

  • :supervisor_name - PostHog instance the snapshot was produced from; used when enabled?/2 and get_flag/2 fire $feature_flag_called events.
  • :distinct_id - resolved distinct ID the /flags request was made for. "" for the empty fallback returned when no distinct_id could be resolved; events are short-circuited in that case.
  • :flags - map of flag key to PostHog.FeatureFlags.Result.t/0.
  • :request_id - request ID returned by /flags.
  • :evaluated_at - server-side evaluation timestamp.
  • :errors_while_computing - whether the response signaled errorsWhileComputingFlags. When true, every event fired from this snapshot includes errors_while_computing_flags in its $feature_flag_error property.
  • :accessed_pid - pid of the Agent tracking accessed keys.

Functions

accessed(evaluations)

@spec accessed(t()) :: [String.t()]

Returns the sorted list of keys accessed via enabled?/2 or get_flag/2 on this snapshot.

Includes keys that were accessed but absent from the snapshot.

enabled?(snapshot, key)

@spec enabled?(t(), String.t()) :: boolean()

Returns whether the named flag is enabled in this snapshot.

Returns false for unknown flags. Records the access. Fires a $feature_flag_called event with full metadata when the flag is present, or with $feature_flag_error: "flag_missing" and $feature_flag_response: nil when it is not.

event_properties(evaluations)

@spec event_properties(t()) :: %{required(String.t()) => any()}

Returns the $feature/<key> and $active_feature_flags properties for this snapshot, suitable for merging into a captured event's properties.

  • $feature/<key> is set to the variant string when present, or to the enabled boolean otherwise. Disabled flags are included with false.
  • $active_feature_flags is the sorted list of keys whose flag is enabled.

Examples

properties = PostHog.FeatureFlags.Evaluations.event_properties(snapshot)
PostHog.capture("page_viewed", Map.merge(%{distinct_id: "u1"}, properties))

get_flag(snapshot, key)

@spec get_flag(t(), String.t()) :: String.t() | boolean() | nil

Returns the variant string, the enabled boolean, or nil for unknown flags.

Records the access. Fires a $feature_flag_called event with full metadata when the flag is present, or with $feature_flag_error: "flag_missing" and $feature_flag_response: nil when it is not.

get_flag_payload(evaluations, key)

@spec get_flag_payload(t(), String.t()) :: any() | nil

Returns the configured payload for the flag, or nil for unknown flags or flags without a payload.

Does not record access for only_accessed/1 or fire a $feature_flag_called event.

keys(evaluations)

@spec keys(t()) :: [String.t()]

Returns the sorted list of flag keys present in the snapshot.

only(snapshot, keys)

@spec only(t(), [String.t()]) :: t()

Returns a copy of the snapshot scoped to the given keys. Unknown keys are silently dropped.

The returned snapshot has its own access tracker. Calls on it do not back-propagate to the parent.

only_accessed(snapshot)

@spec only_accessed(t()) :: t()

Returns a copy of the snapshot scoped to the flags accessed so far via enabled?/2 or get_flag/2.

Returns an empty snapshot when nothing has been accessed yet — including no flags would be more surprising than helpful, since the caller asked for "only what I touched."

The returned snapshot has its own access tracker. Calls on it do not back-propagate to the parent.