Fastify-based notification service. Accepts notification events, persists them via an outbox pattern, and fans them out to delivery channels (email, in-app, Slack) through SQS-backed workers with retry/backoff and dead-letter handling.
- notification-client — the TypeScript
client that upstream services use to emit events into this service. It signs requests with
HMAC-SHA256 and posts them to the
/internal/notification-eventsendpoint handled by the app component below.
- app — HTTP API (Fastify) that accepts notification events and writes to the outbox.
- router — outbox relay: polls PENDING outbox rows and publishes them to the per-channel SQS queues, plus the deadline scheduler.
- worker — per-channel consumers (email via SES, in-app, Slack) that read from SQS and deliver, with retry backoff and a dead-letter queue for failures.
- Postgres — outbox / notification state.
- Redis — nonce/dedup and short-lived state.
- SQS (LocalStack in dev) — channel queues:
notification-events-{in-app,email,slack}.
Full architecture diagram: https://mermaid.ai/app/projects/404a123b-12e3-4172-bdf1-cce75f57a2a0/diagrams/76784c23-3894-4b1a-80d2-b8b703fc9250/version/v0.1/edit
- Node.js and npm
- Docker and Docker Compose
dpo-assistant-prisma— a sibling Prisma package expected at../dpo-assistant-prisma(declared as afile:dependency inpackage.json). Clone it alongside this repo before runningnpm install.
npm install
cp .env .env.local # fill in real values; .env itself is git-ignored
docker compose upThis starts the app (:8200), router (:9201), worker (:9202), Postgres (:5435),
Redis (:6380), and LocalStack SQS (:4566).
| Script | Description |
|---|---|
npm run dev |
Run the API with ts-node |
npm run build |
Compile TypeScript to dist/ |
npm start |
Run the compiled API (dist/index.js) |
npm run router |
Run the outbox relay/router |
npm run worker |
Run the channel workers |
npm test |
Run the Jest test suite |
See docker-compose.yml for the full list of variables each service expects
(DATABASE_URL, REDIS_URL, SQS queue URLs, AWS credentials, etc.). Never commit a
real .env file — it's git-ignored on purpose.