Services
Notifyzr is a set of small services behind one Traefik proxy. Each has its own subdomain of DOMAIN.
| URL | Service | What it is |
|---|---|---|
api.<domain> | api | Public REST API. API-key auth, rate limited. |
app.<domain> | app | Dashboard SPA |
app.<domain>/api | app-api | Dashboard auth (JWT) and organization/key management. The only issuer of sessions. |
admin.<domain> | admin | Site-admin SPA |
admin.<domain>/api | admin-api | Site-admin API — users, organizations, plans, announcements |
docs.<domain> | docs | This documentation |
mcp.<domain> | mcp-server | MCP server for AI assistants |
unsubscribe.<domain> | unsubscribe | Hosted opt-out page |
<domain> | landing | Marketing site |
| — | worker | Consumes every queue: sending, webhooks, automations, fan-out |
| — | toolbox | Cron-scheduled maintenance (key expiry, quota warnings, message pruning) |
Infrastructure
| URL | What it is |
|---|---|
status.<domain> | Public status page (Gatus). No auth. |
grafana.<domain> | Dashboards, pre-provisioned |
prometheus.<domain> | Metrics |
pgadmin.<domain> | Database admin (development) |
mailpit.<domain> | Captured mail (development) |
:15672 | RabbitMQ management UI |
:8090 | Traefik dashboard |
Datastores
- PostgreSQL — everything persistent. Nearly every table is organization-scoped.
- RabbitMQ — jobs, delayed sends, events, dead letters.
- Redis — API rate limiting, and MCP session state.
Scaling
Services are stateless and can be replicated:
bash
docker compose up --scale api=3 --scale worker=2Prometheus discovers replicas through Docker DNS, so each new container is scraped automatically with its own instance label — metrics are stored per instance and aggregated at query time, so scaling never double-counts.
Observability
Every PHP service exposes Prometheus metrics at /metrics. That endpoint is blocked at the Traefik edge and scraped container-direct on the Docker network, so it is never reachable from outside.