$ show binwiederhier/ntfy
ntfy is a self-hostable push notification server implemented in Go with a React PWA front end. It exposes an HTTP API where clients publish messages with PUT/POST to a topic; subscribers receive them over WebSocket, SSE, or long polling. The server goes beyond basic pub-sub: it caches messages in SQLite, PostgreSQL, or memory, supports file/S3 attachments, and fans out to Firebase Cloud Messaging, Web Push, email via SMTP, Twilio calls, and Matrix. A full account system with tiers, ACLs, tokens, reservations, and Stripe billing sits alongside abuse controls like visitor rate limiting and IP bans. The repository also contains a Go client library and CLI for publishing and subscribing. Architecturally, this is a single Go binary with a build-tag feature matrix (e.g. noserver, nofirebase, nowebpush, nopayments) plus a React/Vite SPA served by the same process. Storage is backend-agnostic through interfaces: message.Cache, attachment.Store, user.Manager, and webpush.Store each have SQLite and PostgreSQL implementations, with schema migrations managed by a shared db/schema framework. The code stands out for extensive table-driven tests across both database backends, race-condition coverage, and careful security work such as template execution limits, Web Push endpoint allowlists, and a custom SigV4 S3 signing implementation. Main weaknesses are large central files, duplicated SQL for SQLite/PostgreSQL, and vendored forks of text/template and sprig that require manual synchronization with upstream.
The LLM identified 5 files worth highlighting for reuse:
Generic queue that accumulates items and flushes them once a batch size or interval is reached. Used for async message cache writes. Fully self-contained and easy to extract for any project needing efficient batched persistence, network writes, or event flushing.
Composable rate limiting primitives: fixed-window limiter, token-bucket/rate limiter, and shared limit writers/readers. Used to throttle visitor requests, attachment traffic, and template output. Self-contained and directly reusable in APIs, proxies, or download services.
A dependency-free S3 client implementing AWS Signature Version 4, multipart upload, and path-style/virtual-hosted addressing. Demonstrates non-obvious skill in request signing and chunked uploads; the package can be extracted into any Go project needing lightweight S3 access without the official SDK.
Concurrency-safe ACL cache that resolves exact and wildcard permissions with explicit precedence rules (specific user beats Everyone, longer patterns win, write beats read at equal length). It is a standalone authorization pattern useful for any system needing fast, hierarchical permission checks.
Generic schema migration runner for both SQLite and PostgreSQL with per-store version tracking. It allows the project to keep multiple storage backends synchronized and can be reused for any Go service needing embedded migrations for both databases.