Gotify vs ntfy
Pick ntfy if you want to fire notifications straight from scripts and cron with a one-line curl and subscribe from any device — it's the more flexible pub/sub model. Pick Gotify if you'd rather have a tidy web UI with per-app tokens and a simple, self-contained server for your own alerts.
Side by side
Gotify and ntfy solve the same small but genuinely useful problem: getting a push notification to your phone the moment a backup finishes, a server reboots, or a cron job falls over — without routing any of it through a third-party push service. Both are tiny Go servers you run yourself, both are light enough to forget about, and both do the job well. The decision comes down to how you want to send alerts and how many devices you want to receive them on: a tidy, token-based web app, or a curl-and-topics model that plugs into anything that can make an HTTP request.
The core difference: tokens vs. topics
Gotify is built around applications and tokens. You log into its web UI, create an "application," and it hands you a token; anything that wants to send a notification posts to Gotify with that token. It is a clean, self-contained model — every source of alerts is a named app with its own credential, and the web dashboard shows them all in one place.
ntfy is built around topics. A topic is just a name in a URL, and you
publish to it with a one-line request — curl -d "backup done" http://your-server/mytopic is a complete, working notification. There is no
app to create first and no token to mint for the basic case (you can add access
control and auth when you want it). That difference sounds cosmetic but it is
the whole personality of each tool: Gotify wants you to register a sender, ntfy
wants you to just publish.
For anyone wiring alerts into shell scripts, cron jobs, or CI, ntfy's model is
simply less friction — it turns curl into a notification pipeline you can
drop into a one-liner anywhere.
Subscribing: one app vs. anything
The send side is only half the story; the receive side is where ntfy stretches its lead. Gotify delivers to its own Android client (and the web UI) via a persistent WebSocket connection. It works reliably, but you are subscribing through Gotify's app on Gotify's terms.
ntfy is designed to be subscribed to from almost anywhere: its own Android
and iOS apps, any web browser pointed at the topic URL, or a plain curl
holding the connection open for scripting. Because a subscription is just an
HTTP stream on a URL, you can consume notifications programmatically as easily
as you send them; Gotify also exposes a WebSocket stream, but it needs a client
token and a WebSocket client rather than plain curl. If you want alerts on
multiple platforms — including an iPhone — or want to react to them in code,
ntfy reaches further out of the box — though instant iPhone delivery from a
self-hosted server needs upstream-base-url set so ntfy.sh relays a wake-up
poll, and the docs call the iOS app bare-bones.
Where Gotify pulls ahead: the admin UI
This is the one column that goes the other way, and it is a real point in Gotify's favor. Gotify ships a full web UI: log in, see every application, read message history, manage clients and tokens, all from a polished dashboard. It feels like a finished little product for managing your own alerts.
ntfy's web interface is deliberately minimal — it is excellent for subscribing to a topic and firing test messages, but it is not an administrative console in the same way. Management leans on a config file and the command line rather than a point-and-click dashboard. If you specifically want a graphical place to see and organize everything, Gotify is the nicer home; if you treat notifications as plumbing you configure once and forget, ntfy's sparseness is a feature rather than a gap.
Resources and stack
Here the two are effectively identical, and that is the easy part of the
choice. Both are single Go binaries with no external database to run —
Gotify uses SQLite by default; ntfy keeps messages in memory by default, or in
a SQLite cache file once you set cache-file — so both are rated at a 256 MB RAM floor and 2/5 difficulty. Either one
starts in a single container in a couple of minutes and then sits quietly using
almost nothing. Measured idle at first boot confirms just how little: a fresh
Gotify instance settles at ~5 MB, ntfy at ~13 MB — both a rounding
error next to their documented 256 MB floors, and the small gap between them
isn't worth weighing against the actual decision below. Licensing differs only
slightly and permissively: Gotify is MIT, ntfy is dual-licensed
Apache-2.0 and GPLv2. Neither
the footprint nor the license should tip your decision — this is genuinely a
choice about the sending and receiving model, not the runtime.
Phone-app behavior: priority levels and delivery
Both apps' Android clients go further than "show a notification," and the details are worth knowing before you pick one.
Priority levels. Both support a per-message priority that changes how the
phone reacts, not just what the notification says. ntfy documents five levels
(min/low/default/high/urgent, or 1–5), set via a Priority header on
publish — urgent triggers a long vibration and a pop-over notification,
min lands quietly under the fold in "Other notifications." Gotify's
priority is a number from 0 to 10 that the Android app maps to four
behaviours — no notification (0), icon only (1–3), plus sound (4–7), plus
vibration (8–10) — and the web UI plays a sound from 4 up: workable, but
coarser on the phone than ntfy's five distinct levels.
Delivery: websocket vs. push. Gotify's Android app holds open a persistent
WebSocket connection to your server to receive messages. That is reliable —
provided you exempt the app from Android battery optimization, which Gotify's
README says otherwise kills it — and delivery timing is then entirely up to
your server's uptime, not a third-party push service. ntfy's official app is more nuanced for a
self-hosted server specifically: it documents that it "won't use Firebase for
any self-hosted servers" (Firebase/FCM push is reserved for the official
ntfy.sh host), so a self-hosted ntfy server relies on the same kind of
persistent foreground-service connection Gotify uses for "instant delivery." The
documented trade-off is a permanent foreground notification while that
connection runs (you can hide it in Android's notification settings); the ntfy
FAQ puts the constant connection at about 0–1% battery over 17 hours. The
'minutes to hours' delays the docs warn about apply to Firebase delivery on
ntfy.sh, not to a self-hosted server.
Webhooks and integrations. ntfy has a built-in http action for message
action buttons — tapping a button in the notification can fire an HTTP
request, which is genuinely webhook-shaped and needs no extra software (e.g.
"turn off the lights" as a one-tap action from a notification). Gotify doesn't
build this in; receiving webhooks from third-party services (GitHub,
Prometheus Alertmanager, and similar) is a community-plugin job, via Gotify's
plugin system rather than a core feature. ntfy, by contrast, accepts GitHub,
Grafana and Alertmanager webhooks natively via its pre-defined templates
(?template=alertmanager).
Which should you self-host?
Pick ntfy if…
- You want to fire notifications straight from scripts, cron, or CI with a one-line curl to a topic, with no app to register first.
- You want to subscribe from many places — Android, iOS, the web, or another script — rather than through a single vendor app.
- You like the pub/sub model and are happy managing the server from a config file instead of a heavy dashboard.
Pick Gotify if…
- You want a tidy web UI to see every application, token, and message in one place.
- The per-app token model — one named credential per source — fits how you think about organizing alerts.
- You mainly notify your own Android device and value a polished, self-contained little server over maximum flexibility.
Who should pick neither
Both of these are general-purpose push servers — you decide what triggers a notification and when. If what you actually need is narrower — "tell me when a cron job or backup silently stops running," not "send arbitrary alerts from anywhere" — that's a different job. Healthchecks is built specifically for that dead-man's-switch pattern: your scheduled job pings a URL when it finishes, and Healthchecks alerts you only when the ping doesn't arrive on time, layering its own notification channels on top rather than asking you to wire up the logic yourself.
Choosing between ntfy and Gotify
Reversed, the decision reads the same: default to ntfy if you're wiring alerts into scripts, cron, or CI and want to subscribe from more than one device or platform — its curl-friendly topics and five-level priority system are built for exactly that. Pick Gotify instead if a tidy, self-contained web dashboard with per-app tokens matters more to you than reach, and you mainly notify a single Android device. Both measure a few megabytes idle at first boot, so let the sending and receiving model decide, not the spec sheet.
Running either on a VPS
Both run comfortably on the smallest server you can rent — a single Go binary in 256 MB, no database daemon to feed, and next to nothing to maintain once it is up. There is no meaningful resource gap between them, so let the send-and- receive model decide rather than the spec sheet: ntfy for curl-friendly topics you subscribe to from anywhere, Gotify for a token-based server with a proper dashboard. The step-by-step setups are linked below, and any of the VPS options here has ample room to run either alongside the other services you are already hosting.
Paid link — we earn a commission if you shop through it.
Other comparisons with these apps
The multi-database web client from DBeaver vs. the PostgreSQL-only admin tool.
One conf.yml with an in-browser editor vs. YAML files and Docker label discovery.
The team LLM-app platform vs. the Python-component canvas.