Why self-host your web analytics
Benefits of self-hosted analytics
- Native GDPR compliance: no third-party data transfer, no consent banner required when no cookie is used
- 100% data ownership: CSV/SQL export at any time, long-term retention with no expiry
- Fixed cost: the VPS price does not depend on how many pageviews you record
- Lightweight script (< 2 KB): negligible impact on Core Web Vitals
- No sampling: every pageview is counted, even at high volumes
- Open source: auditable code, no vendor lock-in
Plausible vs Umami: key criteria comparison
Scroll the table
| Criterion | Plausible 3.2 | Umami 3.4 |
|---|---|---|
| Language / stack | Elixir + ClickHouse | Node.js + PostgreSQL |
| Database | ClickHouse (columnar) | PostgreSQL only (MySQL dropped in v3) |
| Interface | Very minimal, single-page | Multi-site, configurable dashboards |
| Funnels | Not in Community Edition (Plausible Cloud only) | Yes, via custom reports |
| Custom events | Yes, with props API | Yes, with props API + TypeScript SDK |
| Heatmaps / Session replay | No | Yes (replay since v3.1, heatmaps since v3.2, 2026) |
| Advanced segmentation | Combined filters | Session segments, property filters |
| Recommended min RAM | 2 GB (ClickHouse) | No published minimum (PostgreSQL, lighter) |
| License | AGPL-3.0 | MIT |
Prerequisites by tool
Plausible requires ClickHouse, a columnar database built for analytics. ClickHouse is powerful but RAM-hungry: plan for at least 2 GB, ideally 4 GB for a comfortable instance. Umami runs on PostgreSQL, which is far lighter: a small VPS is enough for moderate-traffic sites. If your VPS already runs PostgreSQL for another application, Umami integrates without additional resources. As of Umami v3, MySQL is no longer supported; if migrating from an older MySQL install, export and reimport to PostgreSQL first.
Deploying Plausible (or Umami) on a VPS
Clone the official repo (
plausible/community-editionat version v3.2.1 or later, which fixes the critical CVE-2026-8467 flaw, orumami-software/umami) and create a.envfile: neither repo ships a.env.exampleFill in required variables:
BASE_URLandSECRET_KEY_BASE(Plausible) orDATABASE_URLandAPP_SECRET(Umami), generating each secret withopenssl rand -base64 48. Umami'sdocker-compose.ymlships an exampleAPP_SECRETand PostgreSQL password: replace them with.envvariables (${APP_SECRET}), and publish its port as127.0.0.1:3000:3000so only nginx reaches itRun
docker compose up -d— the image pulls ClickHouse/PostgreSQL and auto-migrates the schemaConfigure an nginx reverse proxy with HTTPS (Let's Encrypt) on your chosen domain, and ensure
X-Forwarded-Foris forwarded correctlyAdd the tracking script to your site and verify the first pageview in the dashboard. On Umami, first change the password of the default
adminaccount
Block bots in the analytics nginx vhost only, never in your site's vhost where the rule would also block Googlebot (if ($http_user_agent ~* "(bot|crawler|spider)")) to keep your stats clean without any analytics-side configuration.
Decision tree: Plausible or Umami?
Choose Plausible if…
- You want an interface any teammate understands in 5 minutes without training
- Your team doesn't need session replay or heatmaps
- You have at least 4 GB of RAM on the VPS (ClickHouse earns it)
- You manage several sites from a single minimalist dashboard
- You don't need funnels or revenue tracking when self-hosting (missing from Community Edition, Plausible Cloud only)
Choose Umami if…
- You have a resource-constrained VPS (less than the 2 GB of RAM recommended for Plausible) or PostgreSQL is already installed
- You need heatmaps and session replay (since Umami 3.2, 2026)
- Your team builds custom integrations via the official TypeScript API (
@umami/api-client) - You manage many sites for different clients (native multi-tenant)
- You want to query your data in natural language via an AI assistant using MCP (Umami 3.4, enabled with
MCP_ENABLED=1when self-hosting)
GDPR, CNIL, and ePrivacy compliance: what each tool actually covers
Both tools are designed to work without tracking cookies and without storing complete IP addresses. Plausible hashes the IP with a daily rotating salt; Umami uses a similar approach. Result: no persistent identifier is stored server-side, which allows you to skip the consent banner for analytics alone — provided the script is not combined with other trackers. The French CNIL exempts from consent audience-measurement trackers that serve the site publisher exclusively, produce only anonymous statistics, and allow no cross-matching with other processing, no transfer to third parties and no tracking of the person across sites. The ePrivacy Directive points the same way. Caveat: if you cross-match the data with a third-party advertising solution, the exemption no longer applies; and a VPS outside the EU also raises the question of data transfers under the GDPR. Documenting hosting details (VPS location, retention policy) in your processing register remains mandatory.
Migrating from Google Analytics 4
Steps to move from GA4 to Plausible or Umami
Export GA4 history as CSV via Google Analytics > Reports > Export, or via the GA4 Data API for large volumes — Plausible can import GA4 history (in Community Edition, once the Google integration is configured:
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET); for Umami, keep this export as an archiveRun the Plausible/Umami script alongside the GA4 tag for 2–4 weeks to compare metrics (numbers will differ: GA4 may sample above its quotas, Plausible/Umami count everything)
Verify that critical custom events (forms, clicks, purchases) are replicated via
plausible('goal')orumami.track()Remove the GA4 tag and its
_gacookie once satisfied — update your privacy policy accordinglyDocument the new metrics in your GDPR register: legal basis, retention period, server location
Traffic numbers will often be higher with Plausible or Umami than with GA4 on the same site: being cookieless, they do not wait for visitor consent, whereas GA4 only fully measures visitors who accepted its cookies. The gap varies from site to site with your consent rate — this is not a bug, it is measurement without a banner.
Advanced features: funnels, segments, events and API
At Plausible, multi-step funnels and revenue tracking are reserved for the cloud offer: the self-hosted Community Edition does not include them. Plausible 3.2 (January 2026) does let you limit a shared link to a segment, and version 3.2.1 (May 2026) fixes the critical CVE-2026-8467 flaw: it is the minimum to install. Segmentation relies on combined filters (source, country, device, event properties) that can be saved as segments. The Stats API v2 (POST /api/v2/query) extracts any dimension; the old /api/v1/stats/breakdown endpoint is now marked legacy. Umami 3.4 (September 2026) goes further with session segments — you can group visitors by session properties and replay their journey. Session replay (Umami 3.1, April 2026) and heatmaps (Umami 3.2, June 2026) enable visual behavior analysis. The TypeScript @umami/api-client SDK (generated from OpenAPI) simplifies data pipeline integration. Umami also supports session identity stitching: if a visitor returns on another device and authenticates, sessions are merged into a single profile.
Common troubleshooting
Frequent issues and solutions
- ClickHouse won't start (Plausible): check available RAM (
free -h) — the vendor recommends at least 2 GB of RAM for ClickHouse and Plausible, and the CPU must support SSE 4.2 (or NEON on ARM). If the VPS is tight, add a 2 GB swap file (fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile). Check logs withdocker compose logs plausible_events_db. - Umami migrations stuck: after an update, if the app refuses to start with
relation does not exist, restart the container (docker compose restart umami): on startup, Umami applies pending Prisma migrations itself (prisma migrate deploy); readdocker compose logs umamito find the one that fails. - Pageviews not recorded: verify your site's CSP header allows the analytics domain (
script-src 'self' https://analytics.yourdomain.com). Ad blockers may also block the script — consider proxying it from your own domain. - ClickHouse error after hard restart: if ClickHouse reports a corrupted table, find the table involved in
docker compose logs plausible_events_db, then querysystem.detached_partsviaclickhouse-client, which lists detached parts and why they were detached; if data is missing, restore your latest backup. - Umami v3: errors after migrating from MySQL: Umami v3 dropped MySQL support. If upgrading from v2 with MySQL, export all data first, provision PostgreSQL, then reimport following the official MySQL-to-PostgreSQL migration guide in the Umami docs.
Backing up and restoring your analytics data
Backup strategy for Plausible and Umami
Plausible / ClickHouse: use the
clickhouse-backup createtool (imagealtinity/clickhouse-backup, run in a neighbouring container with access to ClickHouse's data volume) or export critical tables to Parquet viadocker compose exec -T plausible_events_db clickhouse-client --query "SELECT * FROM plausible_events_db.events_v2 FORMAT Parquet" > events_$(date +%Y%m%d).parquetUmami / PostgreSQL: a standard
pg_dumpis enough —docker compose exec db pg_dump -U umami umami > umami_$(date +%Y%m%d).sql. Schedule daily via cron and upload to object storage (S3, Backblaze B2)Test restoration at least quarterly on a staging VPS:
docker compose exec -T db psql -U umami umami < umami_backup.sqlFor Plausible, also back up the Docker volume holding the app's PostgreSQL data (separate from ClickHouse)
Document the restoration procedure in your runbook — an untested backup is not a backup