NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #3291 most downloaded on npm
Last release 4 days ago
01 Oct 2026
Ships on a steady schedule
a new release about every 8 days
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
1 years old
209 releases · first in 2025
One column per month.
1.55.3 Patch Changes #5046 c360da1 Thanks @luke-belton ! - Capture the OpenAI Ads click identifier ( oppref ) as a campaign parameter, so it is set on
c360da1 Thanks @luke-belton! - Capture the OpenAI Ads click identifier (oppref) as a campaign parameter, so it is set on events and as $initial_oppref like every other ad click ID.1.55.2 Patch Changes #5078 f4704ac Thanks @rubychilds ! - Honor filters.holdout during local feature flag evaluation. A user in an experiment holdout
f4704ac Thanks @rubychilds! - Honor filters.holdout during local feature flag evaluation. A user in an experiment holdout now receives the holdout-<id> variant instead of being bucketed into a regular variant, matching how the server evaluates the same flag. The holdout is resolved before the release conditions, so a held-out user never reaches the flag's targeting — including when those conditions would have excluded them, so isFeatureEnabled can return true where it previously returned false. Experiments with an active holdout will see variant assignment change for the held-out share of traffic on upgrade, bringing locally evaluated assignments in line with server-evaluated ones.Updated dependencies [ 9cd8ebd ]:
#5018 9cd8ebd Thanks @turnipdabeets! - Stop dropping long spans that end: maxSpanAgeMs now evicts spans only once maxLiveSpans is reached, so a span that runs past the age limit and then ends is exported, and its children are no longer orphaned.
(2026-09-21)
#4800 aad7464 Thanks @marandaneto! - Respect the definitions response's property_matching_version during local feature flag evaluation. Version 2 uses explicit boolean/string equality and per-member array matching, while missing or other versions retain service legacy matching (including empty-array truthiness). Preserve the version in Node definition caches and Convex persisted definitions, and propagate it through person, group, cohort and dependency evaluation without mixing snapshots during reloads. Existing numeric ambiguity fallback and SemVer parsing policies are unchanged.
(2026-09-21)
Updated dependencies [9cd8ebd]:
1.55.0 Minor Changes #4904 5cfec8b Thanks @lucasheriques ! - Support partial survey responses and persistent resume in React Native, moving surveys to
5cfec8b Thanks @lucasheriques! - Support partial survey responses and persistent resume in React Native, moving surveys toward feature parity across SDKs.1.54.5 Patch Changes #5012 5c12a4c Thanks @yoarajota ! - Coerce survey and product tour property filter values to strings before matching, so a numeri
5c12a4c Thanks @yoarajota! - Coerce survey and product tour property filter values to strings before matching, so a numeric filter value from the /surveys response no longer throws in icontains/not_icontains### Patch Changes - #4977 `0257a29` Thanks @lucasheriques! - Share survey choice and question shuffling between web and React Native through surveys c
0257a29 Thanks @lucasheriques! - Share survey choice and question shuffling between web and React Native through surveys core. Use Fisher-Yates for web questions, preserve Other-last choice ordering, and avoid mutating configured choices.
(2026-09-17)### Patch Changes - #5005 `6545d3f` Thanks @marandaneto! - Fix declaration source mappings for DOMExceptionCoercer. (2026-09-17)
6545d3f Thanks @marandaneto! - Fix declaration source mappings for DOMExceptionCoercer.
(2026-09-17)### Patch Changes - #4885 `39a8980` Thanks @decknamec! - Server-side feature flags now resolve in posthog-node and posthog-edge even when a proxy rewr
39a8980 Thanks @decknamec! - Server-side feature flags now resolve in posthog-node and posthog-edge even when a proxy rewrites the request's User-Agent. Flags restricted to the client runtime now resolve to undefined in these SDKs, where a rewritten User-Agent previously let them through.
(2026-09-15)### Patch Changes - #4941 `07c1045` Thanks @marandaneto! - Capture causes and AggregateError members with relationship metadata and individual stacks,
07c1045 Thanks @marandaneto! - Capture causes and AggregateError members with relationship metadata and individual stacks, limiting output to 50 entries and 1,000 member inspections.
(2026-09-15)### Minor Changes - #4954 `3c68c08` Thanks @marandaneto! - Export the shared Retry-After parser with safe integer caps, GMT HTTP-date handling and rej
3c68c08 Thanks @marandaneto! - Export the shared Retry-After parser with safe integer caps, GMT HTTP-date handling and rejection of non-HTTP dates.
(2026-09-14)### Patch Changes - #4922 `3786cff` Thanks @Mnigos! - Require final 2xx responses for successful writes while preserving immediate-call error handling
### Patch Changes - #4899 `18ae6bb` Thanks @marandaneto! - Share the trySafe utility through @posthog/core. (2026-09-11)
18ae6bb Thanks @marandaneto! - Share the trySafe utility through @posthog/core.
(2026-09-11)1.53.1 Patch Changes #4908 4a3c74b Thanks @turnipdabeets ! - Child spans now share their parent's clock, so a child no longer appears to start before
4a3c74b Thanks @turnipdabeets! - Child spans now share their parent's clock, so a child no longer appears to start before or end after its parent by up to a millisecond, or by more when the system clock is adjusted mid-trace.Updated dependencies [`19e78cc`]:
19e78cc Thanks @turnipdabeets! - Add experimental distributed tracing to posthog-node: startSpan, withSpan and getActiveSpan record spans against a new traces client option. A service with tracing off still forwards an inbound traceparent, including from spans nested inside the one that received it, so a distributed trace is not severed. A traceparent may be passed as the one-element array req.headersDistinct gives. A beforeSpanSend hook sees every span before it is exported and may edit or drop it, and maxAttributesPerSpan, maxEventsPerSpan, maxAttributeValueLength, maxLiveSpans and maxSpanAgeMs bound what a single span and a single process may hold.
(2026-09-10)#4579 19e78cc Thanks @turnipdabeets! - Cap the retry delay for log exports at 30 seconds, the ceiling the logs contract states. It previously doubled to 64 times the flush interval — 192s on web, 640s on React Native — so a log export now resumes within 30 seconds of a failing endpoint recovering, at the cost of more retry requests while that endpoint is down.
(2026-09-10)
#4579 19e78cc Thanks @turnipdabeets! - Keep backing off a failing log flush while new records arrive, instead of the next record resetting the retry to the flush interval.
(2026-09-10)
#4579 19e78cc Thanks @turnipdabeets! - Stop a throwing getter in metrics.resourceAttributes from breaking every metrics export — the key is recorded as [Unserializable] instead.
(2026-09-10)
#4579 19e78cc Thanks @turnipdabeets! - Honor Retry-After when the ingestion endpoint refuses a logs or metrics batch, instead of retrying on the SDK's own schedule alone. A refusal naming a longer wait extends the one being served, up to five minutes from when it started. Retry delays now carry jitter so clients refused together do not return together, and metrics backs off exponentially across consecutive failures rather than retrying on a fixed interval.
(2026-09-10)
#4579 19e78cc Thanks @turnipdabeets! - Logs and metrics now always send service.name and telemetry.sdk.*, even when a resourceAttributes value is too large to encode in full. Previously that value could crowd them out, and the records reached PostHog with no service attribution.
(2026-09-10)
#4579 19e78cc Thanks @turnipdabeets! - Stop sending logs and metrics batches over 10 MiB, or too large to serialize at all, instead of spending a request to discover the endpoint refuses them.
(2026-09-10)
Updated dependencies [19e78cc]:
### Patch Changes - #4887 `0da006c` Thanks @posthog! - Error tracking no longer counts an injected script as your own code. A stack frame is in_app on
0da006c Thanks @posthog! - Error tracking no longer counts an injected script as your own code. A stack frame is in_app only when its filename names a script your app was served — http(s), file, blob, app, capacitor, ionic, a bundler scheme, or a bare path. A frame served over any other scheme, such as an in-app browser bridge on iabjs:// or an extension content script on chrome-extension://, is kept for context but no longer groups the issue under your code.
(2026-09-10)### Patch Changes - #4880 `412c97c` Thanks @marandaneto! - Fix recording package exports, native ESM loading, and strict TypeScript 4.7 consumer compa
412c97c Thanks @marandaneto! - Fix recording package exports, native ESM loading, and strict TypeScript 4.7 consumer compatibility.
(2026-09-10)Updated dependencies [`891eefa`]:
### Patch Changes - #4859 `c356c81` Thanks @marandaneto! - Include the root license and attribution notices in the published core package. (2026-09-09
c356c81 Thanks @marandaneto! - Include the root license and attribution notices in the published core package.
(2026-09-09)### Patch Changes - #4798 `4358915` Thanks @posthog! - fix(error-tracking): collapse repeated frame cycles in parsed stack traces to reduce grouping d
### Minor Changes - #4809 `3a5b322` Thanks @marandaneto! - Add best-effort in-app browser attribution using $webview_app and $webview_app_version, wit
3a5b322 Thanks @marandaneto! - Add best-effort in-app browser attribution using $webview_app and $webview_app_version, without changing existing $browser or $browser_version values. Detect explicit user-agent markers for Facebook, Facebook Lite, Messenger, Instagram, Threads, LinkedIn, Twitter, TikTok, WhatsApp, Snapchat, WeChat, LINE, Google, Bing, Pinterest, Naver, and KakaoTalk. Unknown apps and versions are omitted; missing markers do not imply a standalone browser.
(2026-09-07)Updated dependencies [`74ca945`, `5e74132`]:
74ca945 Thanks @marandaneto! - Clarify feature flag return-value terminology across SDK APIs. A false value is a conclusive off evaluation, while undefined means no evaluation is available. Remote evaluation omits globally inactive flags, whereas backend local evaluation can resolve cached inactive definitions to false.
(2026-09-07)74ca945, 5e74132]:
Updated dependencies [ 426e1fd ]:
### Patch Changes - #4759 `c475070` Thanks @marandaneto! - Preserve explicitly false feature flag values supplied through bootstrap configuration. (20
c475070 Thanks @marandaneto! - Preserve explicitly false feature flag values supplied through bootstrap configuration.
(2026-09-03)Updated dependencies [`41ed3af`]:
dbbb58e Thanks @Ashishjob! - Fix clampToRange discarding a valid fallback value of 0. It used fallbackValue || max, so a 0 fallback (a legitimate value) was treated as absent and replaced by max; it now uses ?? so 0 is honored.
(2026-09-03)41ed3af]:
### Patch Changes - #4727 `ec9354c` Thanks @turnipdabeets! - Drop attributes with an empty key from exported logs and metrics instead of sending them.
ec9354c Thanks @turnipdabeets! - Drop attributes with an empty key from exported logs and metrics instead of sending them. OTLP requires a non-empty key, and the server stored one verbatim, where it appeared as a nameless attribute that filters could not match.
(2026-09-01)### Patch Changes - #4710 `e87820a` Thanks @turnipdabeets! - Add os.name and os.version resource attributes to logs from the browser SDK, overridable
e87820a Thanks @turnipdabeets! - Add os.name and os.version resource attributes to logs from the browser SDK, overridable via logs.resourceAttributes
(2026-09-01)ChatGPT versions its apps differently per platform, so its $browser_version is not comparable across platforms. (2026-09-01)
#4663 6ae173f Thanks @pauldambra! - Detect the Claude, Codex, and ChatGPT apps from their user agent markers: $browser now reports the app name instead of Chrome.
ChatGPT versions its apps differently per platform, so its $browser_version is not comparable across platforms. (2026-09-01)
#4661 444bf35 Thanks @marandaneto! - Match local feature flag string operators, exact-value coercion, and JSON stringification with the flags service.
(2026-09-01)
#4708 6723395 Thanks @turnipdabeets! - Change bigint attributes on logs, metrics and spans to send as an int64 rather than as a string.
(2026-09-01)
1.49.2 Patch Changes #4626 3c650a1 Thanks @nandinitiw ! - Re-translate popover surveys when the display language changes while the survey is on screen
3c650a1 Thanks @nandinitiw! - Re-translate popover surveys when the display language changes while the survey is on screen, either from a browser languagechange event or from identify() updating the language person property. In-progress answers are preserved. $survey_questions[].question and $survey_language on survey sent / survey dismissed now report the text and language the user saw when they answered, not the language active when the event fired. Feedback-button (widget) surveys are unchanged.### Patch Changes - #4636 `74ff567` Thanks @yfwmaniish! - Narrow the pinterest entry in the bot-detection blocklist to pinterestbot, so real users on
74ff567 Thanks @yfwmaniish! - Narrow the pinterest entry in the bot-detection blocklist to pinterestbot, so real users on Pinterest's in-app browser (whose UA also contains the substring pinterest) are no longer misclassified as bots and silently excluded from analytics. The crawler's other UA variant remains covered by the existing generic bot.htm entry, so no bot-detection coverage is lost.
(2026-08-27)### Minor Changes - #4036 `718beee` Thanks @emmayusufu! - Add capturedAt to PostHogLogs.captureLog() for stamping a record with the time and context o
718beee Thanks @emmayusufu! - Add capturedAt to PostHogLogs.captureLog() for stamping a record with the time and context of when the event occurred, and PostHogLogs.clearQueue() for dropping every queued record
(2026-08-27)### Patch Changes - #4616 `7902e44` Thanks @shahidrogers! - Stop crashing when the environment's Math.random() misbehaves. The vendored UUIDv7 generat
#4616 7902e44 Thanks @shahidrogers! - Stop crashing when the environment's Math.random() misbehaves. The vendored UUIDv7 generator builds its random fields from a Math.random()-based nextUint32(), and a nonconformant implementation that returns a value of 1 or greater, or NaN, pushed those fields out of range, so fromFieldsV7 threw RangeError: invalid field value on every event captured. On React Native this is not hypothetical: Hermes implements Math.random with C++ std::uniform_real_distribution, which is documented to occasionally return its upper bound, and affected Android devices crash-looped on startup during the SDK's internal event-queue flush — a path applications cannot wrap in a try/catch. nextUint32() now clamps its result to a valid unsigned 32-bit integer (>>> 0), so a bad random value degrades UUID entropy for that id instead of taking the app down; the timestamp bits are untouched and generated ids remain spec-valid UUIDv7.
(2026-08-27)
#4651 e899b1c Thanks @marandaneto! - Treat omitted local evaluation properties as inconclusive for is_not_set.
(2026-08-27)
### Patch Changes - #4610 `930de19` Thanks @marandaneto! - Share feature flag matching, hashing, variant, and payload evaluation helpers across the No
#4610 930de19 Thanks @marandaneto! - Share feature flag matching, hashing, variant, and payload evaluation helpers across the Node.js and Convex SDKs without changing their runtime-specific SemVer behavior.
(2026-08-25)
#4611 d4eee8f Thanks @marandaneto! - Share survey property matching between the browser and React Native SDKs while preserving their existing missing-value behavior.
(2026-08-25)
### Patch Changes - #4623 `be299df` Thanks @turnipdabeets! - Fix buffered logs being dropped instead of retried after HTTP 408, 429 or 5xx (2026-08-24
be299df Thanks @turnipdabeets! - Fix buffered logs being dropped instead of retried after HTTP 408, 429 or 5xx
(2026-08-24)### Patch Changes - #4614 `3593c43` Thanks @iamomiid! - The Node SDK now sends the raw gzip bytes as the request body instead of wrapping them in a Bl
3593c43 Thanks @iamomiid! - The Node SDK now sends the raw gzip bytes as the request body instead of wrapping them in a Blob. On Node 24.16 and later, reading a Blob request body leaks a native BlobReader that is never released, so a service calling capture() and flush() once per request grew by roughly 2.3 KB of heap per event and never gave it back. This completes the work in #4423: switching to node:zlib removed the compression-time Blob reads, but the body itself was still a Blob and still got read once per request. Compression behaviour, headers and the wire format are unchanged, and the edge build keeps using CompressionStream.
(2026-08-24)### Patch Changes - #4581 `556d235` Thanks @turnipdabeets! - Fix reloadFeatureFlags and reloadFeatureFlagsAsync returning flags evaluated before the c
556d235 Thanks @turnipdabeets! - Fix reloadFeatureFlags and reloadFeatureFlagsAsync returning flags evaluated before the caller's most recent identity or person-property change when several reloads overlap, and stop overlapping reloads from skipping the remote config refresh
(2026-08-21)Updated dependencies [`6322f09`]:
6322f09 Thanks @turnipdabeets! - Fix logs and metrics being silently dropped when an attribute holds a very large integer, a function, a symbol, a sparse array, or a truncated emoji.
Cap log and metric attributes at 20 levels of nesting, 1,000 entries per object and 10,000 values in total, marking anything beyond as [Truncated].
Type OtlpAnyValue.intValue as string | number — code reading that field must handle both. (2026-08-21)6322f09]:
### Patch Changes - #4578 `bae46bf` Thanks @marandaneto! - Drop events when a before-send hook throws instead of sending the unmodified event. (2026-0
#4578 bae46bf Thanks @marandaneto! - Drop events when a before-send hook throws instead of sending the unmodified event.
(2026-08-20)
#4582 aef2f49 Thanks @ablaszkiewicz! - Stop building a stack frame for a window.onerror report that carries no code position, such as the ResizeObserver loop warning. The frame named the document URL rather than a script, so no source map could resolve it. These exceptions now arrive with no stack trace.
(2026-08-20)
### Patch Changes - #4572 `9701637` Thanks @ablaszkiewicz! - Stop counting Chromium stack frames (extension-injected, devtools or string-evaluated cod
9701637 Thanks @ablaszkiewicz! - Stop counting Chromium <anonymous> stack frames (extension-injected, devtools or string-evaluated code) as in-app code.
(2026-08-19)### Patch Changes - #4558 `3f9ba71` Thanks @posthog! - Fall back to the synthetic exception stack when a captured Error has no stack, so frameless fai
### Patch Changes - #4549 `0599fe0` Thanks @ablaszkiewicz! - Recognise Firefox and Safari extension frames when filtering extension exceptions, and st
0599fe0 Thanks @ablaszkiewicz! - Recognise Firefox and Safari extension frames when filtering extension exceptions, and stop counting Safari's masked webkit-masked-url:// frames as in-app code.
(2026-08-18)## 1.48.2 ### Patch Changes - #4413 `7b61aa4` Thanks @posthog! - Fix error tracking coercion reporting the wrong exception type for non-Error objects
7b61aa4 Thanks @posthog! - Fix error tracking coercion reporting the wrong exception type for non-Error objects (e.g. TypeError, ReferenceError) that are thrown by browser extensions or other cross-realm code. Previously these always reported as type Error, burying the real type in the message string. Also fixed a local isError helper shadowing the more robust cross-realm-aware implementation, which caused some errors thrown from iframes or extension isolated worlds to be misclassified.
(2026-08-17)Updated dependencies [`eb05237`]:
0a0206f Thanks @marandaneto! - Normalize capture timestamp overrides to equivalent UTC ISO strings in the browser and Node.js SDKs and shared core.
(2026-08-14)eb05237]:
Updated dependencies [`b2c6830`]:
c9086de Thanks @carlos-marchal-ph! - Public beta captureAi() / captureAiImmediate(): AI events on a dedicated isolated endpoint with the event UUID returned. New enableFullAiCapture option replaces the internal _useAiLane / _enableMultimodalCapture; wrappers route through the AI endpoint and skip redaction/truncation when set (privacy mode still wins).
(2026-08-13)b2c6830]:
## 1.47.1 ### Patch Changes - #4506 `a77115b` Thanks @marandaneto! - Log shutdown timeouts without rejecting, and correct the Node.js shutdown() retur
a77115b Thanks @marandaneto! - Log shutdown timeouts without rejecting, and correct the Node.js shutdown() return type to Promise<void>.
(2026-08-12)Surveys can now display an intro screen before question 1, configured via the new displayIntroScreen, introScreenHeader, introScreenDescription, intro
#4436 80f15a3 Thanks @jakesciotto! - feat(surveys): optional intro screen shown before the first question
Surveys can now display an intro screen before question 1, configured via the new
displayIntroScreen, introScreenHeader, introScreenDescription,
introScreenDescriptionContentType, and introScreenButtonText appearance fields.
The intro is dismissed with a button and records no response, does not affect
completion or partial-response metrics, does not re-fire "survey shown", and is
skipped when a survey is resumed with answers in progress. Intro copy is
translatable like the thank-you message. renderSurveysPreview accepts
previewPageIndex: -1 (exported as INTRO_SCREEN_PREVIEW_INDEX) to preview the
intro screen. (2026-08-10)
Updated dependencies [`75fb719`]:
64ba193 Thanks @marandaneto! - Use Node's zlib gzip implementation for Node SDK payloads to avoid sustained memory growth from frequent Web Streams compression.
(2026-08-06)75fb719]:
Updated dependencies [`3c40b6c`]:
3c40b6c Thanks @marandaneto! - Keep request timeouts active through response body consumption and clarify eventual event UUID deduplication semantics.
(2026-08-05)3c40b6c]:
Updated dependencies [`43d1850`]:
d3c4538 Thanks @posthog! - Keep $referring_domain and canonical utm_*/campaign parameters on minimal $feature_flag_called events. Previously the minimal allowlist stripped every campaign parameter, so a flag-called event landing first in a session could set the session's UTM attribution and channel type to NULL in web analytics.
(2026-08-04)43d1850]:
## 1.46.6 ### Patch Changes - #4363 `821a2c6` Thanks @marandaneto! - Safely capture circular and otherwise unknown telemetry values with a shared JSON
821a2c6 Thanks @marandaneto! - Safely capture circular and otherwise unknown telemetry values with a shared JSON-safe value converter.
(2026-08-04)## 1.46.5 ### Patch Changes - #4235 `7db0e8c` Thanks @hpouillot! - Preserve messages, source locations, and existing stacks from browser errors that d
7db0e8c Thanks @hpouillot! - Preserve messages, source locations, and existing stacks from browser errors that do not provide a same-realm Error object.
(2026-08-03)## 1.46.4 ### Patch Changes - #4381 `f3a71a1` Thanks @marandaneto! - Clear completed lifecycle timeout handles so successful shutdowns do not leave ti
f3a71a1 Thanks @marandaneto! - Clear completed lifecycle timeout handles so successful shutdowns do not leave timers running.
(2026-08-03)## 1.46.3 ### Patch Changes - #4155 `eb0a793` Thanks @ATKasem! - fix: personProperties and groupProperties on the feature flag methods are no longer t
eb0a793 Thanks @ATKasem! - fix: personProperties and groupProperties on the feature flag methods are no longer typed as Record<string, string>, so numeric and boolean values type-check without a cast. Local evaluation already handled them — matchProperty takes Record<string, any> and compares numerically for gt/gte/lt/lte — only the public types disagreed. These now use the shared Properties type (personProperties?: Properties, groupProperties?: Record<string, Properties>), matching setPersonPropertiesForFlags/setGroupPropertiesForFlags so the any can be narrowed later. Types only, no runtime change.
(2026-08-03)## 1.46.2 ### Patch Changes - #4347 `7c3a9af` Thanks @marandaneto! - Preserve events added to a full queue while an earlier batch is being flushed. (2
7c3a9af Thanks @marandaneto! - Preserve events added to a full queue while an earlier batch is being flushed.
(2026-08-03)## 1.46.1 ### Patch Changes - #4332 `b9a241e` Thanks @ioannisj! - Fix identify() leaving a user anonymous when the supplied ID already matches the per
b9a241e Thanks @ioannisj! - Fix identify() leaving a user anonymous when the supplied ID already matches the persisted distinct ID (for example after a non-identified bootstrap seeded the same ID). The user is now marked identified and a person-processed $set event is captured. Ports the same fix from posthog-js (browser) to the shared core used by React Native, Node, and posthog-js-lite.
(2026-07-31)## 1.46.0 ### Minor Changes - #4308 `6e7f3ae` Thanks @ablaszkiewicz! - Emit the release id that posthog-cli injects into your bundle as $release_id on
6e7f3ae Thanks @ablaszkiewicz! - Emit the release id that posthog-cli injects into your bundle as $release_id on $exception events, so PostHog can attach exceptions to a release without joining through symbol sets. Adds getInjectedReleaseId() to @posthog/core. The property is only attached when an injected release id can be read.
(2026-07-30)## 1.45.3 ### Patch Changes - #4325 `3bd8a2d` Thanks @marandaneto! - Fix dead-click false positives on WebKit when the SDK uses an iframe-sourced Muta
3bd8a2d Thanks @marandaneto! - Fix dead-click false positives on WebKit when the SDK uses an iframe-sourced MutationObserver fallback.
(2026-07-30)Surveys stopped being shown while feature flags were still loading, even when a cached enabled value for their internal targeting flag was already ava
#4304 c7099e9 Thanks @lucasheriques! - fix(surveys): only wait for feature flags on surveys that repeat
Surveys stopped being shown while feature flags were still loading, even when a cached
enabled value for their internal targeting flag was already available. Popover and widget
surveys recovered on the next evaluation, but a survey your own code renders (type api)
is evaluated once, so it was dropped for that page load and never reappeared.
That wait is only needed for surveys that repeat, where stored per-survey state is keyed by iteration and cannot be relied on to record that someone already answered. Other surveys keep one stable key that already prevents a repeat display, so they are now evaluated against the cached flag right away. (2026-07-29)
## 1.45.1 ### Patch Changes - #4234 `6c8fde0` Thanks @hpouillot! - Normalize V8 Promise combinator stack frames so input indexes are not treated as so
6c8fde0 Thanks @hpouillot! - Normalize V8 Promise combinator stack frames so input indexes are not treated as source filenames.
(2026-07-23)isFeatureEnabled(key, { defaultValue: false }) now returns the given default when the flag has no value — flags not loaded yet, or no flag with that k
#4222 0f2407b Thanks @turnipdabeets! - feat: add a default-value option to isFeatureEnabled
isFeatureEnabled(key, { defaultValue: false }) now returns the given default when the flag has no value — flags not loaded yet, or no flag with that key — and the return type narrows to boolean. The option name is the same in posthog-js, posthog-js-lite, and posthog-react-native. Without defaultValue, behavior is unchanged: boolean | undefined. (2026-07-22)
0f2407b]:
When the v2 /flags response carries minimalFlagCalledEvents: true (or, for posthog-node local evaluation, the flag-definitions payload carries minimal
#4172 9621830 Thanks @haacked! - send minimal $feature_flag_called events when the server enables it
When the v2 /flags response carries minimalFlagCalledEvents: true (or, for posthog-node local evaluation, the flag-definitions payload carries minimal_flag_called_events: true) and the evaluated flag is not linked to an experiment ($feature_flag_has_experiment === false), $feature_flag_called events are rebuilt from a strict allowlist of flag-evaluation, processing-control, and SDK-identity properties. Super properties, $set/$set_once, the $feature/<key> enumeration, $active_feature_flags, and the context envelope are stripped. Any missing signal (no gate on the response, bootstrapped or locally injected flags, has_experiment unknown) falls back to the full event, and experiment-linked flags always send the full envelope. The gate is stored alongside the cached flags (posthog-js persistence, posthog-node poller state) and is server-controlled, with no SDK-side configuration. before_send runs after the filter and may re-add stripped properties. (2026-07-20)
Your coding agent can read these notes before it upgrades. Set up the MCP server →