targetingKey — optionally carrying durable properties stored by fw-server.
You own the ID. The SDK never auto-generates one.
OpenFeature and the wire still say flagKey for the control point. Identity on that call is always targetingKey.
Why it exists
Percentage assignment hashes(flag, targetingKey). If the key changes every request, users flip variants and the backend fills with junk persons. Registration exists so durable facts (plan, region, device model) do not have to ride on every evaluate.
When to use it
user, org, plan, and region are not reserved SDK fields. kind on register is only 'user' | 'device'. plan and region appear in SDK identity docs as example property names you may send — you choose the keys.
How it relates
Identity rules
- Never auto-generated. No
targetingKeymeans no invented anonymous ID. - Missing key fails safe on backend evaluation: your default +
TARGETING_KEY_MISSING(InvalidContext). requireTargetingKeydefaults to false in the four server SDKs. Set ittrueif you want keyless calls rejected even in tests.
- Node
- Python
- Go
- Java
Two identity paths
These compose; they do not compete.registerTarget/identify— durable properties stored by fw-server (POST /v1/targets/register). Call once per login or device provisioning.- Per-evaluate
attributes— win for that call. Use for request-only facts.
$-prefixed attributes are backend system directives, not person properties. fw_-prefixed target property keys are reserved and stripped server-side.
Whether fw-server persists properties in production, and which predicates it evaluates, is platform-side and NEEDS VERIFICATION. The SDK forwards
targetingKey, attributes, groups, and groupProperties.Registration lifecycle
Registration is idempotent: re-register updates properties. It never throws — login paths must not break. Adapters without the capability (InMemory, local/dev) returnok: false with UnsupportedCapability.
The test-server stub does not implement
POST /v1/targets/register. Register tests use mocks or an injected fetch, not that stub.
What it looks like
- Node
- Python
- Web
- Go
- Java
Groups
Group membership and group properties travel on the evaluation context. Canonical keys:fireweave.groups and fireweave.groupProperties. Plain groups / groupProperties are accepted aliases; canonical keys win if both are present.
Any other fireweave.* context key is rejected with InvalidContext. targetingKey and kind are also reserved in the evaluation context.
.group(...) / .groupProperty(...).
Group identify (creating group profiles) is not a FireWeave extension. Do that with your analytics SDK if you need it.
Privacy (what the SDK actually does)
Evidenced in the SDK privacy review — not a console policy:- The SDK adds no person properties of its own. Whatever you put on the context is forwarded to fw-server (or a vendor adapter where one still exists).
- Prefer derived attributes (
email_domain) over raw PII if you must target on identity-adjacent facts. - Error messages are secret-redacted and must not echo attribute values.
- Signal attributes pass an allowlist. Evaluation context is not that allowlist — evaluate forwards what you send (minus reserved keys).
- Nothing is persisted to disk by the SDK.
Related
- Control points — evaluate with this identity
- Exposures — same
targetingKeyjoin - Quickstart — language-gated register step
- Testing — InMemory does not persist registration