AuthonAuthon Blog
comparison6 min read

Migrating from Google Analytics: Umami vs Plausible vs Fathom

A practical comparison of Umami, Plausible, and Fathom for replacing Google Analytics — with a self-hosting safety lesson from a viral Reddit post.

AW
Alan West
Authon Team
Migrating from Google Analytics: Umami vs Plausible vs Fathom

Last week I was scrolling r/selfhosted and stumbled on a post from someone who'd accidentally exposed their entire LAN to the public internet for two full weeks. Two weeks. Their NAS, their cameras, their Home Assistant — all sitting there waiting for Shodan to index them. It was a port-forward mistake combined with a UPnP-happy router, and the kind of story that makes every self-hoster reach for their firewall rules.

That post hit at an awkward time for me. I'd just spun up a self-hosted analytics stack to replace Google Analytics on three of my side projects, and I started questioning whether I actually wanted another service exposed to the internet. So I spent a weekend benchmarking the major privacy-focused analytics tools — Umami, Plausible, and Fathom — and figuring out which ones actually fit different threat models.

Here's what I found.

Why migrate off Google Analytics in the first place

The migration motivation usually breaks down into three buckets:

  • GDPR / privacy law: GA4 still requires cookie banners in the EU for most setups, and the legal situation around US data transfers is a mess.
  • Page weight: the GA4 script is roughly 50KB gzipped, which is brutal for a content site that's otherwise lean.
  • Data ownership: you can't actually query your own raw events without piping them through BigQuery.

None of these are dealbreakers on their own. Stacked together, they push a lot of indie devs to look elsewhere.

Side-by-side: Umami, Plausible, Fathom

Quick comparison of the three I evaluated. I'm only including things I verified from the official docs and pricing pages — if something isn't here, assume I didn't check it thoroughly.

| | Umami | Plausible | Fathom |
|---|---|---|---|
| License | MIT | AGPLv3 | Proprietary |
| Self-host option | Yes (official) | Yes (official Community Edition) | No |
| Hosted option | Umami Cloud | Plausible Cloud | Fathom Cloud (only option) |
| Script size | ~2KB | ~1KB | ~2KB |
| Cookie-free | Yes | Yes | Yes |
| Database | PostgreSQL or MySQL | PostgreSQL + ClickHouse | N/A (hosted only) |

Fathom dropped its open-source "Lite" version a while back, so if self-hosting is a hard requirement, you're picking between Umami and Plausible. Both are legitimately good. The differences only show up once you start using them.

The migration: from GA4 to Umami

Umami was my first stop because the install is genuinely the simplest self-hosted analytics setup I've used. Here's the docker-compose I ended up with, behind a Cloudflare Tunnel so I never expose a public port (more on that in a minute):

yaml
# docker-compose.yml
services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    environment:
      DATABASE_URL: postgresql://umami:${DB_PASSWORD}@db:5432/umami
      DATABASE_TYPE: postgresql
      # Generate with: openssl rand -base64 32
      APP_SECRET: ${APP_SECRET}
    depends_on:
      db:
        condition: service_healthy
    restart: always

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - umami-db:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U umami']
    restart: always

volumes:
  umami-db:

Replacing the GA snippet on the frontend was a one-liner swap.

Before (GA4):
html
<!-- gtag loads ~50KB and sets cookies by default -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXX');
</script>
After (Umami):
html
<!-- One script, no cookies, no consent banner needed in most jurisdictions -->
<script
  defer
  src="https://analytics.example.com/script.js"
  data-website-id="your-uuid-here">
</script>

Custom events are also dramatically less ceremony than GA4. Where GA4 wants you to define event parameters in the admin UI before they show up cleanly in reports, Umami just accepts whatever you throw at it:

js
// Track a signup with arbitrary metadata
window.umami.track('signup', {
  plan: 'pro',
  referrer: document.referrer,
});

Where Plausible pulled ahead

I also ran Plausible in parallel for two weeks on one site, because I wanted goal funnels and the UTM breakdown view, which are both more polished in Plausible's UI. The script tag is similarly minimal:

html
<script
  defer
  data-domain="example.com"
  src="https://plausible.example.com/js/script.js">
</script>

Things Plausible does better than Umami today, based on my actual usage:

  • Goal funnels out of the box, with a cleaner UI.
  • Email reports are nicer to look at if you're sending weekly digests to non-technical stakeholders.
  • ClickHouse backend scales further if you have serious traffic.

Things Umami does better:

  • Simpler ops — one Postgres database, no ClickHouse to babysit.
  • Multi-tenant by default — easier if you're tracking many sites under one install.
  • Lower resource floor — I run it on a $5 VPS with no complaints.

Back to the LAN exposure thing

Here's where the Reddit post comes back in. If you self-host anything — analytics, a wiki, a media server — please don't poke holes in your router. The blast radius when you misconfigure is enormous, and you usually don't notice until something has been indexed by a scanner.

My rule after that thread:

  • Never rely on UPnP. Disable it on the router.
  • Put self-hosted services behind a tunnel (Cloudflare Tunnel, Tailscale Funnel, or a reverse proxy on a VPS).
  • Audit what's exposed with shodan.io by searching your home IP.

A Cloudflare Tunnel config for the Umami instance above looks like this — no inbound ports opened on the home network:

yaml
# ~/.cloudflared/config.yml
tunnel: your-tunnel-id
credentials-file: /etc/cloudflared/creds.json

ingress:
  - hostname: analytics.example.com
    service: http://localhost:3000
  - service: http_status:404

I haven't tested the new Tailscale Funnel feature at scale yet, but for a single-user analytics dashboard it's probably the lowest-friction option.

So which one should you pick?

Honest take, based on three projects:

  • Pick Umami if you want the simplest self-hosted setup, run multiple sites, and prefer MIT licensing.
  • Pick Plausible if you need polished goal funnels and email reports, or you'd rather pay them to host it and forget about ops.
  • Pick Fathom if you specifically don't want to think about hosting at all and don't need self-hosting on the table.

For most indie projects, Umami self-hosted behind a tunnel is the sweet spot — privacy-friendly, GDPR-compliant out of the box, and crucially, not sitting on a public port waiting for some teenager with masscan to find it.

The original Reddit post was a good reminder that the threat model for self-hosting isn't "someone will try to attack me specifically." It's "the entire internet is constantly scanning every IP, all the time." Plan accordingly.

Migrating from Google Analytics: Umami vs Plausible vs Fathom | Authon Blog