Skip to content

Add PostgreSQL read-only replica support#1648

Merged
binwiederhier merged 8 commits into
mainfrom
postgres-replica
Mar 13, 2026
Merged

Add PostgreSQL read-only replica support#1648
binwiederhier merged 8 commits into
mainfrom
postgres-replica

Conversation

@binwiederhier
Copy link
Copy Markdown
Owner

Summary

  • Add db.DB wrapper that supports routing read queries to PostgreSQL read replicas via round-robin with automatic health checking and fallback to primary
  • Introduce Beginner interface so ExecTx/QueryTx work with both *sql.DB and *db.DB
  • Route read-heavy queries in message cache, user manager, and web push store to replicas via ReadOnly()
  • New --database-replica-urls flag (opt-in, no behavior change when unconfigured)

Configuration

database-replica-urls:
  - postgres://user:pass@replica1:5432/ntfy
  - postgres://user:pass@replica2:5432/ntfy

Design

  • db.DB wraps a primary *sql.DB and optional replicas
  • ReadOnly() returns a *sql.DB from a healthy replica (round-robin) or falls back to primary
  • Replicas are health-checked via ping every 5 seconds (cached with atomic CAS)
  • All writes, transactions, and correctness-critical reads stay on primary
  • SQLite stores are unaffected (wrapped with db.NewDB(sqlDB, nil) for uniform typing)

Test plan

  • go test ./... passes (all existing tests, no replicas = ReadOnly returns primary)
  • Manual test with PG primary + streaming replica
  • Verify writes never route to replicas
  • Verify automatic fallback when replica is down

@binwiederhier binwiederhier marked this pull request as ready for review March 13, 2026 01:18
@binwiederhier binwiederhier merged commit a82ede8 into main Mar 13, 2026
4 checks passed
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Mar 15, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [binwiederhier/ntfy](https://github.com/binwiederhier/ntfy) | minor | `2.18.0` → `2.19.0` |
| [binwiederhier/ntfy](https://ntfy.sh/) ([source](https://github.com/binwiederhier/ntfy)) | minor | `v2.18.0` → `v2.19.0` |

---

### Release Notes

<details>
<summary>binwiederhier/ntfy (binwiederhier/ntfy)</summary>

### [`v2.19.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.19.0)

[Compare Source](binwiederhier/ntfy@v2.18.0...v2.19.0)

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:**

- Support [PostgreSQL read replicas](https://docs.ntfy.sh/config/#postgresql-experimental) for offloading non-critical read queries via `database-replica-urls` config option ([#&#8203;1648](binwiederhier/ntfy#1648))
- Add interactive [config generator](https://docs.ntfy.sh/config/#config-generator) to the documentation to help create server configuration files ([#&#8203;1654](binwiederhier/ntfy#1654))

**Bug fixes + maintenance:**

- Web: Throttle notification sound in web app to play at most once every 2 seconds (similar to [#&#8203;1550](binwiederhier/ntfy#1550), thanks to [@&#8203;jlaffaye](https://github.com/jlaffaye) for reporting)
- Web: Add hover tooltips to icon buttons in web app account and preferences pages ([#&#8203;1565](binwiederhier/ntfy#1565), thanks to [@&#8203;jermanuts](https://github.com/jermanuts) for reporting)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS4yIiwidXBkYXRlZEluVmVyIjoiNDMuNTkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/4755
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant