← All comparisons

dif vs PostHog

Checked Oct 7, 2026

This page compares dif with two PostHog products, feature flags and experiments. PostHog flags live in PostHog: you create and roll them out in its web app, and a flag can be turned off with no redeploy. Experiments run on top of those flags and use the events PostHog already captures as metrics, with Bayesian or frequentist statistics built in. dif is a file format and a compiler: each flag is a Markdown file in your repo, dif build compiles it into a TypeScript client, and a change reaches users with your next deploy. PostHog is the better tool when a flag must change without a deploy, when your services are not JavaScript, or when your product analytics are already in PostHog. dif fits a TypeScript codebase where a flag change should be a reviewed pull request and evaluating a flag should cost no request.

Side by side

RowdifPostHog
Where flags liveOne Markdown file per flag or experiment under dif/experiments/, in your git repo.In PostHog. You create and roll out flags in the PostHog web app. Its API and MCP server manage the same flags. [1]
How a change shipsEdit the file, merge the pull request, run dif build, deploy the app. There is no runtime toggle.Change the flag in PostHog. The docs describe turning a flag off with no redeploy. Client SDKs request flags when they initialize or a user is identified; server SDKs using local evaluation poll for definitions every 30 seconds by default. [1][4][3]
Runtime dependencyNone. dif build compiles the active files into dif/generated/client.ts and @dif.sh/sdk hashes the user ID with SHA-256 in-process. No request to evaluate a flag.Requests to PostHog. By default a server-side flag check is a network round trip to the /flags API. With local evaluation and a secret API key the server SDK fetches definitions in the background and evaluates in-process, and returns no value until the first poll completes. [3]
SDK languagesJavaScript and TypeScript only. Adapters for React, Svelte, the Vercel Flags SDK and an OpenFeature server provider.The libraries listed include JavaScript web, React, Next.js, Vue.js, Android, iOS, Flutter, React Native, Node.js, Python, Go, Java, .NET, Ruby, PHP, Elixir and Rust. Local evaluation is documented for the nine server SDKs. [9][3]
Experiment analysisNot in the open-source core. Exposures and dif.track() calls go to two handler functions you own, or to Dif Cloud, which reports lift with a 95% confidence interval.Built in. Every experiment is backed by a flag that randomizes users and records exposure. Any captured event can be a funnel, mean or ratio metric, synced warehouse tables can be metrics too, and results use Bayesian or frequentist statistics. [8]
Pricing modelThe CLI and SDK are free. Dif Cloud is optional: $50 per month per workspace with 1,000,000 events and unlimited seats, then $0.02 per 1,000 events. Cloud has no free tier.Billed per request to the /flags endpoint. The first 1,000,000 requests each month are free, then $0.0001 per request up to 2 million, falling in tiers to $0.00001 above 50 million. Experiments share that billing and free tier. The free plan has 1 project. Platform packages start at $250 per month. [6][5][7]
LicenceMIT for the CLI, the SDK and every adapter.The PostHog repo is MIT (expat) except the ee directory, which has its own licence. The posthog-foss repo has the proprietary code removed. [11]
Self-hostingNothing to host. There is no flag server; the flags run from your repo and your build. Dif Cloud is a hosted product.A free Docker Compose deployment exists under the MIT licence. PostHog calls self-hosted deployments officially unsupported, gives no customer support for them, and keeps all paid-plan features Cloud-only. The README puts its scale at about 100k events per month. [10][11]
Agent and context supportdif init writes guidance into CLAUDE.md, AGENTS.md, .cursor/rules/dif.mdc and .github/copilot-instructions.md and installs four skills. dif build writes dif/context.json, a summary of active experiments. Dif Cloud serves experiment verdicts to agents over a read-only MCP server at cloud.dif.sh/mcp.A hosted MCP server at mcp.posthog.com installs with npx @posthog/wizard mcp add. Its tools create, update, schedule and soft-delete feature flags. [12][13]
Flag valuesString variant ids only. No typed values, no JSON payloads, no remote config.Three flag types: release toggle (boolean), multiple variants with rollout percentages, and remote config. A payload can be any valid JSON type. [2]
Targeting rulesEquality and list membership on attributes declared in dif/config.yaml. No ranges, regex, semver or nested groups.Release conditions match on person properties, cohorts and groups, with percentage rollouts. Operators include contains, ends with and semver comparisons. [1][2]
Scheduled changesNone. No scheduled rollouts and no automatic ramp.The web app can schedule a change to a flag. The MCP server can schedule one too, including recurring schedules. [1][13]
What a flag check costsNothing is metered in the open-source core. Dif Cloud bills events (exposures and dif.track() results), not evaluations.Each /flags request is billable. A local evaluation poll counts as 10 requests when definitions changed and 1 when they did not. [4][5]

The dif column is checked against the dif repository at v0.7.0. The PostHog column comes from the pages listed under Sources. If a row is out of date, open an issue.

Which one to choose

Choose PostHog if

  • A flag has to change without a deploy. PostHog flags are edited in its web app. In dif, turning a flag off is a merge, a dif build and a deploy.
  • Your product events are already in PostHog. An experiment there can use any captured event as a funnel, mean or ratio metric with no extra wiring. The dif open-source core computes no statistics.
  • Your services are written in Python, Go, Ruby, Java, .NET, PHP, Elixir or Rust, or you ship native mobile apps. dif has a JavaScript and TypeScript SDK and nothing else.
  • You need JSON payloads or remote config on a flag. dif variants are string ids.
  • You target by cohort, group or semver, or you want a change scheduled for later. dif audiences match declared attributes by equality or list membership, and nothing is scheduled.
  • Your traffic fits in 1,000,000 flag requests a month and you want hosted flags and experiment results for $0. Dif Cloud has no free tier.

Choose dif if

  • Your app is TypeScript and a flag change can wait for the next deploy.
  • You want every flag change reviewed in the same pull request as the code it gates, with git history as the record.
  • You want flag evaluation with no request and no API key. @dif.sh/sdk has no dependencies and assigns by hashing the user ID, so there is nothing to wait for on a cold start.
  • You do not want flag cost to grow with page loads and identify calls. dif evaluations are not metered.
  • You want the hypothesis, owner, metrics and decision stored in the flag file, and dif conclude to append the learning to dif/surfaces/<name>.md.
  • You want CI to fail when two active experiments target one surface without a shared exclusion_group. dif validate exits 1 with error E007.

Moving from PostHog to dif

dif has no PostHog importer. Migration is by hand, one flag at a time. The two can run side by side, and you can keep PostHog for analytics after the flags have moved.

  1. List the flags your code still reads. Flags that need a no-deploy off switch, a schedule or a JSON payload should stay in PostHog.
  2. For each flag you move, run dif new <id> --surface <name>. Copy the variant keys into variants and the rollout percentages into weight. Weights must sum to 100. Set status: active.
  3. Rewrite release conditions as audience.include and audience.exclude on attributes declared in dif/config.yaml. A condition dif cannot express (a cohort, a semver comparison, a contains match) has to be computed in dif/audiences/<name>.ts and declared as a boolean or enum attribute.
  4. Replace each flag check with dif("<id>", { ... }) and one branch per variant. Move payload values into those branches; dif has no payloads.
  5. Decide where exposures go. dif init --events custom scaffolds dif/events/exposure.ts and dif/events/track.ts, two functions you own, and you can capture events to PostHog from them. PostHog says every experiment is backed by a PostHog flag, so plan to analyse dif exposures as ordinary events there, or connect Dif Cloud.
  6. Run dif validate, then dif build. Add "prebuild": "dif build" to package.json, because dif/generated/ is gitignored.
$ npm install -g @dif.sh/cli

Sources

Every PostHog claim on this page comes from one of these pages. Pricing and features change; the date is when we read each one.

  1. PostHog docs: Feature flags read Oct 7, 2026
  2. PostHog docs: Creating feature flags read Oct 7, 2026
  3. PostHog docs: Server-side local evaluation read Oct 7, 2026
  4. PostHog docs: Feature flags common questions (billing) read Oct 7, 2026
  5. PostHog docs: Cutting feature flag costs read Oct 7, 2026
  6. PostHog pricing page read Oct 7, 2026
  7. PostHog platform packages read Oct 7, 2026
  8. PostHog docs: Experiments read Oct 7, 2026
  9. PostHog docs: Libraries read Oct 7, 2026
  10. PostHog docs: Self-host PostHog read Oct 7, 2026
  11. PostHog/posthog README read Oct 7, 2026
  12. PostHog docs: MCP server read Oct 7, 2026
  13. PostHog docs: Feature flags in the MCP server read Oct 7, 2026