--- snapshot-1781342048+++ snapshot-1789251377@@ -2,7 +2,35 @@ Release notes from ntfy -2026-06-04T18:44:15Z tag:github.com,2008:Repository/420503947/v2.24.0 2026-06-05T00:40:31Z +2026-08-27T20:16:48Z tag:github.com,2008:Repository/420503947/v2.28.0 2026-08-27T20:38:30Z + +v2.28.0 + +
This is a hardening release. A single topic on ntfy.sh was polled continuously with poll=1 and no since cursor, which replays a topic's entire cache on every request. The changes below bound what one replay can cost, close two fields that had no size limit at all, and fix an ordering bug found while digging into it.
Bug fixes + maintenance:
/topic1,topic2/json?poll=1, #1297)40057 and 40058). Neither field had a size limit before, unlike the message body; on ntfy.sh the 99.9th percentile is 212 bytes for titles and 244 for tagssince cursor returns a topic's entire cache, which was previously unbounded and could reach tens of megabytes on a busy topic, so one request could allocate that much on the server. The newest messages that fit are kept and a truncated response carries an X-Messages-Truncated: 1 headervisitor-attachment-daily-bandwidth-limit now also covers messages replayed from the message cache by poll requests, not just attachment traffic. A poll without a since cursor returns a topic's entire cache, so a topic that is cheap to fill can be re-read for many times its own size; polls beyond the budget are rejected with HTTP 429 (error code 42905) before anything is written. Note that heavy pollers now consume the same budget as attachment downloads, so operators serving both may want to raise the limitThis release lets you sign in with your verified email address instead of your username, which should help if you ever signed up with an email and then forgot which username you picked. It also hardens the message templating engine against a few ways a small template could eat a lot of memory, and it drops the "experimental" label from PostgreSQL support, which has been running ntfy.sh for a while now.
I also did a bunch of refactoring in, mostly in preparation for being able to cluster ntfy nodes and scale the service horizontally. It'll be a while until then, ... baby steps.
Security:
Template: yes) to 32 KB, limit printf widths and precisions to below 1000, and limit indent/nindent to 100 spaces, preventing excessive memory use from a single small templateFeatures:
Bug fixes + maintenance:
twilio packagemetrics packageuser_phone table in the SQLite user database referencing a dropped table after the v2.14 schema migration; repaired automatically by a new migrationThis is a hotfix release, useful pretty much only for ntfy.sh. It was adds the ability to track abusive IPs mor efficiently, reducing the load on the IP banning services and preventing them from falling behind and leaving abusers unbanned for too long. It works by tracking HTTP errors, and writing out a ban file that fail2ban can read and ban offenders instantly. See ban-feed for details.
Features:
ban-file, ntfy tracks a weighted strike budget per visitor and appends abusive IPs to a file that fail2ban can tail and ban on sight (ban-file, ban-window, ban-threshold, ban-weights; see ban-feed)Redo the banning logic, ban.Service
binwiederhier tag:github.com,2008:Repository/420503947/v2.26.1 2026-07-18T06:41:25Z + +v2.26.1 + +Hotfix: Add ban-file/ban-threshold/ban-weights as a more lightweight …
binwiederhier tag:github.com,2008:Repository/420503947/v2.26.0 2026-07-09T19:18:45Z + +v2.26.0 + +This release hardens message templates, which are now executed with a hard-capped execution timeout. This closes
a denial-of-service hole.
On the web app side, it adds configurable date and time formats, a smoother loading and page-transition experience,
and a fix that strips unsafe URL protocols from rendered Markdown.
Security:
Template: yes), #1826, thanks to @alanturing881 for reporting)Features:
Bug fixes + maintenance:
GET /account now reads from the primary database instead of a read replica, so the account view no longer shows stale data right after a change when replicas lag behindjavascript:, data:, ...) from links and images in Markdown-rendered messages, so they no longer trigger an uncaught "React has blocked a javascript: URL" error (thanks to @jvoisin for reporting)This release adds password reset via email, and reworks email verification to use durable, link-based magic links (replacing the old in-memory 6-digit codes). Email stays optional at signup; a user can reset their password only once they have a verified "primary" (recovery)email.
All of this work is probably not useful for self-hosters, but it hopefully will be useful for me, since I do have to reset accounts on a regular basis.
Security issues:
crypto/rand) instead of a clock-seeded PRNGFeatures:
ntfy user reset-pass CLI command for adminsX-Email: yes target) with verified/unverified state in the account UIBug fixes + maintenance:
X-Email: yes (also true/1) now sends to your primary verified email regardless of the smtp-sender-verify setting (previously it was rejected unless verification was enabled); it requires being logged in with a verified addressst_...) so cross-device subscription sync works under auth-default-access: deny-all (#733, #1795, thanks to @lmorchard for the contribution)<, >, and & as \u003c/\u003e/\u0026 in JSON responses (#1511, #1512, thanks to @wunter8 for the contribution)Bug fixes + maintenance:
This release adds the ability to verify email addresses using the smtp-sender-verify flag. This is a change that is required because ntfy.sh was used to send unsolicited emails and the AWS SES account was suspended. Going forward, ntfy.sh won't be able to send emails unless the email address was verified ahead of time.
Features:
smtp-sender-verify config flag, allowing server admins to require emailThis is a small bugfix release that only affects high volume S3 backends that struggle with HTTP/2.
Bug fixes + maintenance:
disable_http2=true S3 URL option to work around HTTP/2 stream errors with DigitalOcean Spaces and other S3-compatible providers (#1678/#1679)This release is another step towards making it possible to help scale ntfy up and out 🔥! With this release, you can store attachments in an S3-compatible object store as an alterative to the directory. See attachment store for details.
⚠️ Important note: With this release, ntfy will take full control over the attachment directory or S3 bucket. Files/objects in the configuredattachment-cache-dirthat match the message ID format (12 chars, matching^[A-Za-z0-9]{12}$), and have no entries in the message database will be deleted. Do not use a directory or S3 bucket asattachment-cache-dirthat is also used for something else.This is a small behavioral change that was necessary because the old logic often left attachments behind and would not clean them up. Unless you have re-used the attachment directory for anything else (which is hopefully never done), this should not affect you at all.
Features:
attachment-cache-dir config option (#1656/#1672)Bug fixes + maintenance:
This is another small bugfix release for PostgreSQL, avoiding races between primary and read replica, as well as to further reduce primary load.
Bug fixes + maintenance:
This is a bugfix release to avoid PostgreSQL insert failures due to invalid UTF-8 messages. It also fixes database-url validation incorrectly rejecting postgresql:// connection strings.
Bug fixes + maintenance:
database-url validation rejecting postgresql:// connection strings (#1657/#1658)This is a fast-follow release that enables Postgres read replica support.
To offload read-heavy queries from the primary database, you can optionally configure one or more read replicas using the database-replica-urls option. When configured, non-critical read-only queries (e.g. fetching messages, checking access permissions, etc) are distributed across the replicas using round-robin, while all writes and correctness-critical reads continue to go to the primary. If a replica becomes unhealthy, ntfy automatically falls back to the primary until the replica recovers.
Features:
database-replica-urls config option (#1648)Bug fixes + maintenance:
This is the biggest release I've ever done on the server. It's 14,997 added lines of code, and 10,202 lines removed, all from one pull request that adds PostgreSQL support.
The code was written by Cursor and Claude, but reviewed and heavily tested over 2-3 weeks by me. I created comparison documents, went through all queries multiple times and reviewed the logic over and over again. I also did load tests and manual regression tests, which took lots of evenings.
ntfy.sh was successfully upgraded to 2.18.0 (though not with Postgres backend yet, as per the rollout plan).
I'm kindly asking the community to test the Postgres support and report back to me if things are working (or not working). There is a one-off migration tool (entirely written by AI) that you can use to migrate.
Features:
database-url config option (#1114/#1619, thanks to @brettinternet for reporting)Bug fixes + maintenance:
line breaks in HTML-only emails received via SMTP (#690, #1620, thanks to @uzkikh for the fix and to @teastrainer for reporting)Bug fixes + maintenance: