ADR 006 — ntfy.sh deploy notifications¶
Status: Accepted Date: 2026-05-09
Context¶
Production deploys need a notification channel. The on-call engineer (currently the founding engineer) needs to know when a deploy succeeded, when one failed, and when a long-running discovery worker run failed in a way that the application's own error handling could not recover from.
The candidates were:
- PagerDuty — the industry-standard option. Per-user pricing that is hard to justify at the current customer count.
- Slack webhook to a
#deployschannel — easy, but adds Slack to the deployment-critical path. Outages in Slack already happen often enough to be worth avoiding as a notification channel. - Email — reliable but easy to ignore. Email is where alerts go to die.
- ntfy.sh — lightweight pub-sub over HTTP, self-hostable, free, push notification on iOS / Android with no app-store account ceremony.
Decision¶
Use ntfy.sh on a self-hosted topic for production deploy notifications.
The deploy script (scripts/deploy-dev.sh) emits two messages per
deploy:
- Start —
priority: low, no sound. Records the SHA, the actor, and the target environment. - End —
priority: highon failure (sounds the alert),priority: lowon success. Records the outcome and a link to the build log.
The ntfy topic is silent on success and loud on failure. The on-call engineer subscribes through the ntfy iOS / Android app and sees the push notification within a few seconds.
The webhook fan-out (Plan 78) for customers is not the same channel. ntfy is internal-engineering only; customer-facing webhook events go through cp-api's signed webhook delivery on the customer's own SIEM / Slack / Teams.
Consequences¶
Positive¶
- Zero ongoing cost. The ntfy topic runs on the same VPS as a half-dozen other small internal tools.
- No vendor lock-in. ntfy is open source; if the public ntfy.sh service disappears tomorrow, we run our own broker on the same VPS.
- Push notifications without an app-store developer account. Critical for "small team, no admin overhead".
- The two-priority pattern (low for routine, high for failure) matches the engineering team's tolerance for alert fatigue.
Negative¶
- ntfy is unencrypted in transit by default. We use HTTPS to the broker, but the topic name itself is the only access control. Anyone who guesses the topic name can subscribe. The current topic names are unguessable but not authenticated; an authenticated topic per Plan 104 follow-up would harden this.
- Single point of failure on the VPS. If the broker goes down, deploys still work, but no one is told. We accept this because failed deploys also fail loudly in the deploy script's exit code, which Container Apps surfaces in the portal.
- When we hire engineer #2 (see Hiring), we will need pager rotation. ntfy supports topic-level subscription per device, so the move to two engineers is operationally one extra device subscribing — but rotation logic ("Bob is on call this week, not Alice") is not built in. That is when this ADR will be revisited.