PostHog Handbook Library / Onboarding

656 words. Estimated reading time: 3 min.

Chrome extension billing case study: Wildfire Systems

Summary

Wildfire Systems implemented PostHog in a Chrome Extension environment. Due to how extensions handle session and identity persistence, they experienced unusually high event volume and feature flag calls, which led to inflated billing.

This document explains the technical causes, the customer's solution, and how to identify similar cases using Metabase.

Technical root cause

| Issue | Explanation | |------|-------------| | PostHog re-initialized on every extension wake | Chrome extensions create a new runtime context when switching from idle to active. Each context re-initialized PostHog without access to prior storage. | | A new distinct_id was created each time | Since local storage is isolated per context, the PostHog SDK could not persist the ID. This triggered a new anonymous ID on each wake cycle. | | identify() was called repeatedly | Each new ID triggered a comparison to the persisted UUID. Since they always differed, identify() was called each time. | | identify() triggered reloadFeatureFlags() | Every call to identify() refreshed feature flags. | | /flags requests were billed, even when quota-limited | PostHog counted these requests toward the usage quota, even if the response returned no flags. | | Added budget mid-cycle had no effect | When the team increased their billing limit, it did not retroactively unlock flags. Only new requests after the monthly reset were allowed. |

Fix implemented by the customer

The Wildfire team applied the correct approach:

  1. Persisted a shared UUID via chrome.storage.local

This ID was generated once, then reused across all extension contexts.

  1. Bootstrapped PostHog with the UUID

On every initialization, the distinct_id was passed via bootstrap.

  1. Avoided calling identify() unnecessarily

The team checked if the existing distinct_id matched the UUID before calling identify().

  1. Minimized /flags requests

Bootstrapped feature flag values were passed during init, reducing the need for real-time flag fetches.

  1. Used PostHog dashboard to monitor

The "My PostHog Billable Usage" dashboard showed real-time data to verify that fixes worked.

How to spot this in metabase

If a customer is using a Chrome Extension without proper initialization, you will often see the following patterns in the usage dashboard:

1. Extremely high identify event counts
2. /flags usage is abnormally high
3. Total event volume appears inflated without a matching frontend footprint
4. Usage patterns appear to "pulse" or reset regularly
5. No batch exports, minimal standard library usage
6. High $set, $identify, $groupidentify volume with few custom events

When you see these signs together, it is a good idea to ask: "Are you using PostHog in a browser extension product or other ephemeral context?"

If confirmed, you can share bootstrapping and identity persistence best practices.

---

Recommendations for extension developers

| Task | Details | |------|---------| | Persist ID manually | Use chrome.storage.local to persist UUID | | Bootstrap identity | Pass the UUID during posthog.init() with bootstrap.distinctID | | Avoid repeated identify() | Only call identify() if the ID has changed | | Reduce /flags usage | Use bootstrap.featureFlags and disable polling if needed | | Monitor proactively | Use the "My PostHog Billable Usage" dashboard | | Educate early | Customers should be aware that extensions require manual handling |

Canonical URL: https://posthog.com/handbook/onboarding/chrome-extension-billing-case-study-wildfire

GitHub source: contents/handbook/onboarding/chrome-extension-billing-case-study-wildfire.md

Content hash: 5d106882bfa026de

Static reader notes
  • MDX_COMPONENT_STATIC_ADAPTER: Adapted interactive MDX components for static reading: PrivateLink.