Self-hosted PostHog, according to PostHog
Read this first. You can self-host PostHog, and PostHog would rather you did not. Its own documentation calls self-hosted deployments "officially unsupported", asks for a 16 GB machine, and points you to Cloud unless you expect fewer than 300k events a month. PostHog Cloud is free up to 1M events a month. Self-hosting therefore costs money to get you a smaller allowance.
That is the whole decision, and most guides on this page's search results still describe a product that changed underneath them. Everything below was read from PostHog's own docs, repository and installer script on 2026-09-09.
What changed, and what most guides still say
| What older guides still say | What is true on 2026-09-09 | Source |
|---|---|---|
| The hobby stack is roughly 7-11 containers | docker-compose.hobby.yml on master defines 37 services | docker-compose.hobby.yml |
Pin a release such as v1.43.0 | "We don't do tagged releases for self-hosted PostHog" | posthog.com/docs/self-host |
| An 8 GB VPS is the sweet spot | Docs ask for "4 vCPU, 16GB RAM, and more than 30GB storage" | posthog.com/docs/self-host |
| Self-hosting gets you the paid features for free | "All paid-plan features are Cloud-only" | posthog.com/docs/self-host |
| Unlimited events, because you own the box | PostHog steers you to Cloud above 300k events, 1k recordings or 300k /flags calls a month | posthog.com/docs/self-host |
| Community support is available | "We don't offer customer support for product, infrastructure, or other questions for self-hosted instances" | posthog.com/docs/self-host |
This is not new hostility. PostHog announced in February 2023 that it was sunsetting its Kubernetes deployment: regular Helm chart updates ceased after 31 May 2023, with security updates on the last version promised for at least 12 months beyond that. It affected what PostHog then called "about 3.5% of our users", and Docker Compose has been the only self-hosted path since. What has changed since 2023 is the size of that Compose file.
What is actually in the hobby stack now?
We counted the top-level services: keys in docker-compose.hobby.yml on master on 2026-09-09. There are 37.
| Group | Services | Count |
|---|---|---|
| Datastores | db (postgres:15.12-alpine), clickhouse, redis7, valkey, elasticsearch | 5 |
| Event streaming | kafka, zookeeper, kafka-init (redpanda v25.1.9) | 3 |
| Object storage | objectstorage (MinIO), seaweedfs | 2 |
| Django app | web, worker, asyncmigrationscheck, temporal-django-worker | 4 |
| Node ingestion | plugins, ingestion-general, ingestion-sessionreplay, ingestion-error-tracking, ingestion-logs, ingestion-traces, recording-api | 7 |
| Rust services | capture, capture-logs, replay-capture, property-defs-rs, personhog-replica, personhog-router, feature-flags, hypercache-server, cymbal, cymbal-resolution | 10 |
| Workflow engine | temporal, temporal-admin-tools, temporal-ui | 3 |
| Everything else | browserless (Chromium v2.51.2), proxy, livestream | 3 |
Three things follow from that list. Temporal and Elasticsearch are now hard dependencies, which is a second workflow engine and a second search index on top of ClickHouse. Ten of the services are separate Rust binaries, which is why the compose file carries context: ./posthog/rust build stanzas even though the installer runs --no-build --pull always and pulls prebuilt images instead. And a headless Chromium container ships in the default stack.
Our 2026-05-02 measurement of ~2.1 GB idle is obsolete and we have not re-run it. It was taken against the 11-service stack of the time. Do not size a server from it. Size from PostHog's documented 16 GB.
How much RAM does self-hosted PostHog need?
PostHog gives two different answers, and it is worth knowing both before you buy a server.
| Source | Requirement | Read on |
|---|---|---|
posthog.com/docs/self-host | "something equivalent to a Hetzner VM with 4 vCPU, 16GB RAM, and more than 30GB storage" | 2026-09-09 |
bin/deploy-hobby, line 15 | "You REALLY need 8GB or more of memory to run this stack" | 2026-09-09 |
The safe assumption is 16 GB. The 8 GB warning is a line of shell that has not been revised as services were added to the compose file, and it says "or more" rather than "is enough". Buying to the 8 GB number leaves nothing for Elasticsearch, Temporal and Chromium, all of which arrived after that warning was written.
Storage deserves its own thought. 30 GB is the documented floor, but session recordings land in MinIO and grow with traffic, and ClickHouse keeps the raw event table. Neither shrinks on its own.
What does self-hosting cost against Mixpanel, Amplitude and PostHog Cloud?
Every price and allowance in this table was read from the vendor's own pricing page on 2026-09-09.
| Product | Free allowance per month | Paid entry tier | Pricing model |
|---|---|---|---|
| PostHog Cloud | 1M events, 5k recordings, 1,500 survey responses | pay-as-you-go once a card is added | usage-based |
| PostHog self-hosted | no licence cap; PostHog steers you to Cloud above 300k events | your server bill | fixed |
| Mixpanel | Free plan, up to 1M events | Growth, "Starts at $0", up to 20M events | usage-based |
| Amplitude | Free plan, 2M events "forever" | Plus, "Starts at $0", first 2M events free, scales to 70M | usage-based |
Neither Mixpanel nor Amplitude publishes a flat entry price any more. Both plans start at $0 and meter upward, so any single monthly figure quoted for them, including the $25 and $995 this page carried before 2026-09-09, is invented. There is no Mixpanel "Starter" plan and no Amplitude "Starter" plan.
Now the arithmetic that matters. A 16 GB Liquid Web Managed VPS is $145/mo subject to change · verified 2026-09-09 at the regular rate, which is about $1,740 a year, and PostHog advises running it below 300k events a month. Three of the four rows above give you more than 300k events a month for nothing.
Self-hosting PostHog is not a cost-saving measure at hobby volume. It is a data-custody measure. Buy it when custody is the requirement.
Should you self-host PostHog?
| Your situation | Do this |
|---|---|
| Under 1M events/month, no data-residency constraint | PostHog Cloud free tier. Nothing to run, and it is a larger allowance than PostHog recommends self-hosting at. |
| Contractually barred from third-party processors, or air-gapped | Self-host on 16 GB, and budget for the operations. |
| You need SSO, advanced permissions or any paid-plan feature | Cloud. "All paid-plan features are Cloud-only." |
| You want pageview counts, not product analytics | Plausible or Umami. Both still ship supported self-hosted editions. |
| You want a vendor who answers support tickets about your server | Not self-hosted PostHog. The docs say so outright. |
How do you install it?
PostHog documents exactly one path, and hand-rolled Compose files that predate the 37-service layout will not produce a working instance. Use the script.
- Provision an Ubuntu 22.04 VPS with 4 vCPU, 16 GB RAM and 30 GB or more of storage. The installer is Ubuntu-only; it calls
aptand adds Docker'sjammyrepository. - Point an A record at the box. The installer asks for the exact domain and uses it for TLS, and it rejects a bare IP address.
- Run the installer:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/posthog/posthog/HEAD/bin/deploy-hobby)"
- Answer its prompts. It asks for a version tag (press enter for
latest), the domain, your sudo password, and optionally an Anthropic API key for PostHog AI and an OpenAI key for SQL and regex assist. Both AI keys are optional and can be added later. - Wait. The script says "we will need to wait ~5-10 minutes for things to settle down, migrations to finish, and TLS certs to be issued", and it polls
localhost/_healthfor up to 10 minutes before giving up. - Open your domain and complete the setup wizard to create the first admin account.
Two things worth knowing before you run it. The script clones the whole PostHog repository to disk, then copies docker-compose.base.yml and docker-compose.hobby.yml out of it, so the working directory is a git checkout you can inspect and re-run from. And it posts a magic_curl_install_start event to us.i.posthog.com with your domain as the distinct_id before it does anything else. That is one HTTP call, it is visible in plain text in the script, and you can delete those lines before running it if telemetry is the reason you are self-hosting in the first place.
To upgrade later, PostHog documents a matching script:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/posthog/posthog/HEAD/bin/upgrade-hobby)"
There is no version to pin and no changelog to read between upgrades, because there are no tagged releases. You are tracking master. Take a snapshot of the VPS before every upgrade; that snapshot is your only rollback.
Which features do you actually get?
PostHog's repository is MIT-licensed except for the ee/ directory, which carries its own licence. The free tier of the product, which is what a self-hosted instance runs, covers product analytics, session replay, feature flags, experiments, surveys and error tracking. The ingestion-sessionreplay, feature-flags and cymbal services in the compose file are there for exactly those.
What you do not get is anything PostHog sells on a paid plan, because "all paid-plan features are Cloud-only". If SSO or advanced project permissions are on your requirements list, self-hosting cannot satisfy them, and no amount of server sizing changes that.
How do you get your data back out?
Two backends hold your data, and an export has to cover both. PostgreSQL holds users, dashboards, feature-flag definitions and experiment configuration. ClickHouse holds every event.
# App config, dashboards, flags, experiments
docker compose exec db pg_dump -U posthog posthog > posthog_postgres.sql
# Raw events (large — compress on the way out)
docker compose exec clickhouse clickhouse-client \
--query "SELECT * FROM posthog.events FORMAT JSONEachRow" \
| gzip > posthog_events.jsonl.gz
If the destination is PostHog Cloud rather than a competitor, PostHog documents a self-hosted to Cloud migration path built on its own posthog-migration-tools repository. Rehearse it against a snapshot before you plan a cutover date around it.
Where PostHog still wins
None of the above is an argument that PostHog is a bad product. It replaces a product-analytics tool, a session-replay tool, a feature-flag service and an experimentation platform with one system and one SDK, and the free Cloud allowance is genuinely large. Its own docs are unusually blunt about the limits of self-hosting, which is more than most vendors manage.
The honest read is narrower than "self-host PostHog to save money". Run it yourself when custody of the event data is a requirement you cannot negotiate, size for 16 GB, and accept that you are operating 37 containers with no support contract and no release to pin. Everyone else is better served by Cloud, or by something smaller from the self-hosted analytics comparison. If deployment tooling is the part you dread, Coolify manages Compose stacks on your own VPS.
PostHog still publishes a Docker Compose deployment and an installer script, and both worked when we read them on 2026-09-09. But its documentation states that self-hosted deployments are officially unsupported, that PostHog offers no customer support for self-hosted instances, and that it makes no guarantees about the stack working on your infrastructure. PostHog announced the end of its Kubernetes deployment in February 2023, and regular Helm chart updates stopped after 31 May 2023. Treat self-hosted PostHog as a maintained open-source distribution rather than a supported product.
There is no version. PostHog's docs state plainly that it does not do tagged releases for self-hosted PostHog, and every change ships continuously from master into the same images its Cloud runs. The installer defaults to the 'latest' tag, and its own output warns against the 'latest-release' option because tagged releases are no longer created. Practically, that means you cannot pin a known-good version or read a changelog between upgrades, so snapshot the server before running the upgrade script.
PostHog's documentation asks for 4 vCPU and 16 GB RAM; its installer script prints a warning saying you need 8 GB or more. Both were read on 2026-09-09. The 8 GB line predates the current compose file, which now includes Elasticsearch, a three-container Temporal cluster and a headless Chromium container that were not in the older stack. Size for 16 GB. Our own 2.1 GB idle measurement from May 2026 was taken against an 11-service stack and no longer applies.
Almost never at hobby volume. PostHog Cloud is free for 1M events, 5k session recordings and 1,500 survey responses a month, while PostHog's own docs steer you toward Cloud if you expect more than 300k events a month on a self-hosted box. A 16 GB Liquid Web Managed VPS is $145/mo regular, verified 2026-09-09, which is roughly $1,740 a year for a smaller recommended allowance and no support. Self-host for data custody, residency or contractual reasons, not to save money.
Yes. Session replay, feature flags, experiments, surveys and error tracking are all free-tier features, and the compose file carries dedicated services for them, including ingestion-sessionreplay, feature-flags and cymbal for error tracking. What you do not get is anything PostHog sells on a paid plan: its docs state that all paid-plan features are Cloud-only, which covers SSO and advanced permissions. Session recordings are written to the MinIO object-storage container, so plan disk growth accordingly.
Common mistakes and fixes
The installer script fails partway through, or you want to run it on something other than Ubuntu.
`bin/deploy-hobby` is written for Ubuntu only. It calls `apt update`, `apt install`, and `add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable"`, and it pins `containerd.io=2.2.0-2~ubuntu.22.04~jammy` (read live from the script on 2026-09-09). On Debian, Rocky or Alma it will fail at the Docker step. It also installs its own docker-compose v2.33.1 binary into /usr/local/bin and then drives the stack with the `docker-compose` v1-style command, so a host that already has the Compose plugin ends up with two. Provision an Ubuntu 22.04 VPS, or read the script and run its final two steps by hand: copy `posthog/docker-compose.base.yml` and `posthog/docker-compose.hobby.yml` into place, then `docker compose up -d --no-build --pull always`.
Containers start, then the box swaps or the OOM killer takes services out.
PostHog's docs ask for 16 GB; the installer script only warns you need '8GB or more' (both read 2026-09-09). The 8 GB figure is the older number and it predates the current 37-service compose file, which adds Temporal, Elasticsearch, a Chromium container and ten Rust services. Size for 16 GB. Check what is actually eating the box with `docker stats --no-stream` before adding RAM: ClickHouse and Elasticsearch are the two that grow without asking, and Elasticsearch will happily take a multi-gigabyte heap if you leave its defaults alone.
Kafka or Zookeeper is unhealthy and events are not ingesting.
Kafka cannot elect a controller until Zookeeper finishes leader election, and on a loaded VPS that ordering times out. Check Zookeeper first with `docker compose logs zookeeper --tail 20`, then `docker compose restart zookeeper`, wait 15 seconds, then `docker compose restart kafka`. `WARN Timeout expired while fetching topic metadata` in the Kafka log means the broker is still starting rather than broken; give it 60 more seconds. The installer itself budgets 5-10 minutes for the whole stack to settle and issue TLS certificates on first run, and it gives up after 10.