This release fixes cache writes under load. On ntfy.sh, hourly cron bursts overwhelmed the batch writer: messages took up to 40s to reach the database (so poll=1 and since= missed them) and publishes stalled. Batches are now written in one statement, publishes no longer wait on the writer, and PostgreSQL connections stay idle instead of reconnecting.
Features:
- Timezone support for delayed notifications via
X-Timezoneheader,timezonequery param or JSON field; the web app sends the browser's timezone (#1967/#1924, thanks @beemines) - RFC 3339 timestamps for delayed notifications, e.g.
At: 2026-12-10T11:00:00-05:00(#1931, thanks @ALPHACOM-Brehmer)
Bug fixes + maintenance:
- Fix delayed message visibility and stalled publishes under bursts: multi-row
INSERTper batch, non-blocking publishes (100-batch buffer), and no scheduled-message lookup unless a sequence ID is set (#2006) - Fix a panic in the account token-update endpoint caused by a concurrent anonymous request racing on the shared visitor; now returns HTTP 401
- Fix messages lost on shutdown: the write queue is flushed and
ntfy servehandlesSIGTERM/SIGINTgracefully pool_max_idle_connsnow defaults topool_max_conns, so PostgreSQL connections are reused instead of re-opened- Fix
since=<message-id>replaying a topic's full history when the ID wasn't on the read replica yet; it's now resolved on the primary - Use the PostgreSQL row estimate for
messages_cachedinstead of aCOUNT(*)every minute - Detect Markdown when
Content-Typehas parameters or is uppercase (#1995, thanks @cipherprofessor) - Fix the Alertmanager template's bogus
0001-01-01end time and merged start/end lines (#1946/#1940, thanks @justadityaraj and @deferred) - Embed the time zone database (
time/tzdata) so named time zones work on ARM Docker images and minimal runtimes - Build with Go 1.27; minimum Go version to build is now 1.26
- Groundwork for clustering (node registry, util primitives, reserved config options); not usable yet (#1991, #1997, #2001, #2003)