Notifier Runbook

Last updated: 2026-06-04 (Notify connector bundle readiness update)

Purpose

Operational steps to deploy, monitor, and recover the Notifier service. Notifier is the deployable host (WebService + Worker) that composes the shared Notify toolkit (src/Notify) into the Notifications Studio. It owns the PostgreSQL notify schema and the Valkey/Redis (or NATS JetStream) notification queue.

Audience: operators and on-call engineers who deploy, monitor, and troubleshoot the Notifier service in a Stella Ops deployment.

Companion Notify web-only service (src/Notify, slot 29) shares the same notify schema and toolkit; this runbook targets the Notifier host (slot 28).

DEPLOYMENT NOTE (verify against the compose you run): in the current active stack (devops/compose/docker-compose.stella-services.yml), Slot 28’s WebService container (notifier-web) is commented out / merged into notify-web— only notifier-worker runs as a standalone Notifier deployable. So although the StellaOps.Notifier.WebService codebase below is real and owns the management API surface, in that profile the admin/ management REST routes are served by the consolidated notify-web (slot 29) and the Notifier ships only its worker. The notifier-web block is retained (commented) for rollback. The legacy split-container profile (docker-compose.stella-ops.legacy.yml) behaves the same way.

Pre-flight

Deploy

  1. Apply the supported Compose or Offline Kit profile with image digests pinned. The Notifier images are stellaops/notifier-web and stellaops/notifier-worker. In the current active compose only stellaops-notifier-worker is enabled; the notifier-web container is commented out (its API surface is served by the consolidated notify-web, slot 29). Deploy notifier-web separately only if you uncomment that block.
  2. Set config (env-var prefix NOTIFIER_; __ maps to config section nesting):
    • NOTIFIER_NOTIFIER__STORAGE__POSTGRES__CONNECTIONSTRING (section notifier:storage:postgres)
    • NOTIFIER_NOTIFIER__QUEUE__TRANSPORT = redis (or nats) and NOTIFIER_NOTIFIER__QUEUE__REDIS__CONNECTIONSTRING (section notifier:queue)
    • Authority/Router auth wiring via the standard Router / Authority sections.
    • ASPNETCORE_URLS for the WebService listener (default container port 8080; local dev https://localhost:10280 / http://localhost:10281).
  3. Verify liveness/readiness: WebService GET /healthz returns 200 Healthy (ASP.NET health-check format, not a JSON ready flag). For the companion notify-web host, GET /readyz returns 503 with missing base connector names when the InApp/InAppInbox base plug-ins are absent or mounted at the wrong notify:plugins:directory. The Worker exposes its own worker health endpoints via MapWorkerHealthEndpoints (includes the queue health check).

NOT IMPLEMENTED: there is no warm-cache admin endpoint (POST .../admin/warm); rules and templates are loaded lazily/per-request and from durable storage.

Monitor

The Worker emits OpenTelemetry instruments via the StellaOps.Notifier meter. Instrument names (dot-notation as emitted; a Prometheus exporter renders these with _/_total suffix conventions):

SLO alerting rules ship in docs/notifications/operations/alerts/notify-slo-alerts.yaml and reference the exporter metric names notify_delivery_success_total, notify_delivery_total, notify_backlog_depth, and notify_delivery_duration_seconds_bucket. CAVEAT: those alert-rule names do NOT map 1:1 onto the instruments the worker actually emits — the code emits notify.delivery.attempts (tagged by status, not a separate success counter), notify.delivery.duration, and notify.queue.depth (per-channel gauge), with no instrument literally named notify.delivery.success, notify.delivery (total), or notify.backlog.depth. Wiring the alerts to live data therefore requires recording rules / relabeling that derive the alert-rule series from the emitted instruments; the shipped rules are not satisfiable directly against the raw exporter output.

Common operations

All management routes are under /api/v2/notify (v1 routes are deprecated and emit Deprecation/Sunset headers, sunset 2026-03-31). Tenant scoping is via the validated stellaops:tenant claim; gateway-forwarded tenant headers are envelope context, not the Notifier data-isolation source.

NOT IMPLEMENTED as described in earlier drafts: there is no :replay delivery verb (use /retry), no channels/{id}:refresh-secret (use security/webhook/{id}/rotate), and no per-tenant pause admin flag in the WebService surface.

Failure recovery

Auditing

Determinism safeguards

On-call checklist