Bootstrapping PostHog SDKs

Contents

Bootstrapping seeds a PostHog SDK with data your app already knows when the SDK initializes. This makes identity, session, or feature flag state available before the SDK finishes its first network request.

Bootstrapping is available in the JavaScript web, React Native, iOS, Android, and Flutter SDKs.

How bootstrapping works

Pass known state in the SDK's bootstrap configuration before initialization:

  1. Your app gets the state it needs, such as a signed-in user ID or server-evaluated Feature Flags.
  2. Your app passes that state to bootstrap when it initializes PostHog.
  3. The SDK applies the state immediately.
  4. The SDK persists or replaces each value according to its lifecycle.

ValuePurposeWhat happens next
Distinct IDStart the SDK with a known anonymous or identified identityThe SDK applies or reconciles the ID according to the platform's persistence rules
Identified stateTell the SDK whether the distinct ID belongs to an identified personThe SDK treats the ID as anonymous or identified and merges identities when required
Session IDContinue the same session across PostHog initializationsThe JavaScript web SDK uses it as the active session ID
Feature Flags and payloadsMake server-evaluated flags available immediatelyThe next complete /flags response replaces the bootstrapped values

The JavaScript web SDK uses distinctID, isIdentifiedID, and sessionID. React Native, iOS, Android, and Flutter use distinctId and isIdentifiedId. Only the JavaScript web SDK supports bootstrapping a session ID.

Bootstrap an identity

Use distinctID and isIdentifiedID when your app knows the person's identity before SDK initialization. Include the same distinct ID in server-side and client-side requests so events, sessions, and feature flag evaluations belong to the same person.

Set isIdentifiedID to true for a signed-in ID, such as a database ID. A previous $identify event isn't required. Set it to false, or omit it, for an anonymous ID.

posthog.init('<ph_project_token>', {
api_host: 'https://us.i.posthog.com',
defaults: '2026-05-30',
bootstrap: {
distinctID: 'distinct_id_of_your_user',
isIdentifiedID: true,
},
})

When isIdentifiedID is true, the JavaScript web, iOS, Android, and Flutter SDKs reconcile the bootstrapped ID with any persisted identity:

  • No persisted identity – The SDK uses the bootstrapped ID and marks it as identified without emitting $identify.
  • An anonymous identity exists – If the IDs match, the SDK marks the existing identity as identified without emitting $identify. If they differ, the SDK calls identify() to link the anonymous activity to the bootstrapped ID. This emits $identify when capturing is enabled. While opted out, only the local identity changes.
  • The same identified identity exists – The SDK keeps it without emitting a redundant $identify.
  • A different identified identity exists – The SDK preserves the existing identity and emits a warning. Call reset() before initialization when you intend to switch users.

The automatic merge follows your person profile settings. If person profiles are set to never, the SDK preserves a different anonymous identity instead of calling identify().

Use bootstrap when your app knows the signed-in identity before SDK initialization. If your app loads the identity asynchronously, call identify() when it becomes available instead.

Bootstrap a session ID

Use sessionID with the JavaScript web SDK to continue a session across PostHog initializations. This is useful when tracking a session across domains because it preserves one session count and a connected Session Replay.

Get the current session ID by calling posthog.get_session_id() and pass it to the next initialization. The session ID must be a valid UUID v7, unique to the person, timestamped no later than the first event in the session, and no more than 24 hours before the last event in the session.

Web
posthog.init('<ph_project_token>', {
api_host: 'https://us.i.posthog.com',
defaults: '2026-05-30',
bootstrap: {
sessionID: 'session_id_of_user_session',
},
})

See the cross-domain tracking tutorial for a complete implementation.

Bootstrap Feature Flags

Pass server-evaluated feature flag values and payloads to bootstrap to make them available when the SDK initializes. The SDK uses these values until it receives fresh values from PostHog.

See bootstrapping Feature Flags for evaluation consistency, flag lifecycle, local evaluation, and implementation examples.

Behavior on mobile SDKs

The iOS, Android, and Flutter SDKs bootstrap through PostHogBootstrapConfig and persist identity and flags on the device. Assign config.bootstrap before calling setup(). Bootstrapping requires iOS SDK 3.66.0+, Android SDK 3.55.0+, or Flutter SDK 5.31.0+.

React Native uses a bootstrap option like the JavaScript web SDK instead of PostHogBootstrapConfig. Bootstrapped identity doesn't overwrite persisted identity. When both bootstrapped and persisted flags exist, persisted values take precedence.

  • Bootstrapped identity applies during setup. On a fresh install, setting it before setup() means events captured synchronously during initialization (like Application Installed) carry your distinct ID instead of the SDK-generated UUID.
    • An anonymous bootstrap (isIdentifiedId: false, the default) seeds the anonymous ID only when none is persisted yet. Once an anonymous ID exists on disk, or the person has been identified, the SDK ignores it.
    • An identified bootstrap (isIdentifiedId: true) is for a signed-in identity available to your app (for example, from a backend session token). On a fresh install, it seeds the distinct ID, marks the person identified, and generates a separate device ID. On a returning install, a matching anonymous ID is marked identified without emitting $identify; a different anonymous ID is merged via identify() when person profiles are enabled. This emits $identify unless capturing is opted out. A different, already-identified person is left untouched.
  • Bootstrapped flags are served until the first /flags response, then replaced. A complete /flags response takes over entirely, so bootstrapped-only keys don't persist past it. Only enabled flags are seeded: a true boolean or a non-empty variant string. A false or empty value is dropped, matching posthog-js. Seed payloads with the separate featureFlagPayloads option. Flag values and payloads must be JSON-serializable, or they're dropped. Bootstrapped flags are cleared on reset().

The feature-flags-loaded signal fires as soon as bootstrapped flags are applied, so startup logic can read them immediately. These SDKs don't support the sessionID bootstrap option. When person profiles are set to never, the SDK preserves a different anonymous identity instead of merging it into an identified bootstrap.

Flutter web: bootstrap isn't applied on Flutter web because the web SDK hooks onto an already initialized posthog-js instance. Configure bootstrap in your posthog.init({...}) call instead.

Community questions

Was this page useful?