Skip to content

witharthur/data-heroes

Repository files navigation

Notification Preferences Service

A production-style TypeScript backend that acts as the source of truth for notification preferences, quiet hours, regional policy overrides, and delivery evaluation.

Tech Stack

  • Node.js 22
  • TypeScript in strict mode
  • Fastify
  • Prisma ORM
  • PostgreSQL
  • Zod
  • Luxon
  • Pino
  • Vitest
  • Docker Compose
  • OpenAPI Swagger UI

Architecture

The service follows clean architecture:

  • src/domain: domain enums, entities, errors, notification classification, quiet-hours rules
  • src/application: use-case services and repository ports
  • src/infrastructure: Prisma client, mappers, repository adapters
  • src/api: Fastify app, routes, validation, error handling, composition root
  • src/shared: logger and reference data
  • src/tests: unit and API tests with in-memory repositories

Application services depend on repository interfaces. Prisma is isolated in infrastructure so business rules can be tested without a database.

Environment Setup

Create .env from .env.example:

cp .env.example .env

Required values:

DATABASE_URL="postgresql://user:password@localhost:5432/notification_preferences"
PORT=3000
NODE_ENV=development
LOG_LEVEL=info

Optional Docker Compose values:

POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=notification_preferences
POSTGRES_PORT=5432
HOST=0.0.0.0

Keep real credentials only in .env. The file is ignored by git.

Local Development

Install dependencies:

npm install

Generate Prisma Client:

npx prisma generate

Apply migrations:

npx prisma migrate dev

Seed demo data:

npm run seed

Run the API:

npm run dev

The service starts at http://localhost:3000.

Swagger UI is available at http://localhost:3000/docs.

Docker

Set the Docker values in .env, then run:

docker compose up --build

The app container runs Prisma migrations before starting.

Scripts

npm run build
npm run typecheck
npm test
npm run prisma:generate
npm run prisma:migrate
npm run prisma:deploy
npm run seed

API

Health

curl http://localhost:3000/health

Get Merged Preferences

curl http://localhost:3000/users/user-1/preferences

Returns default preferences merged with user-specific overrides and quiet hours.

Update User Preference

curl -X POST http://localhost:3000/users/user-1/preferences \
  -H "Content-Type: application/json" \
  -d '{"notificationType":"marketing_email","channel":"email","enabled":false}'

Update Quiet Hours

curl -X POST http://localhost:3000/users/user-1/preferences \
  -H "Content-Type: application/json" \
  -d '{"quietHours":{"start":"22:00","end":"08:00","timezone":"Europe/Berlin"}}'

Evaluate Delivery

curl -X POST http://localhost:3000/evaluate \
  -H "Content-Type: application/json" \
  -d '{"userId":"user-1","notificationType":"marketing_email","channel":"email","region":"EU","datetime":"2026-05-21T21:30:00Z"}'

Example response:

{
  "decision": "deny",
  "reason": "blocked_by_quiet_hours"
}

Business Rules

Evaluation priority:

  1. Global policy
  2. User preference
  3. Quiet hours
  4. Default preference

Global policies override all lower-priority rules. Quiet hours block marketing notifications only; transactional notifications continue to default or policy evaluation. Preference and quiet-hours updates are idempotent.

Tests

npm test

Coverage includes defaults for new users, user preference overrides, quiet-hours evaluation, global policy blocking, idempotency, and API validation.

Production Improvements

  • Add authentication and authorization.
  • Add admin endpoints for default preferences and global policies.
  • Add audit tables for preference and policy changes.
  • Add request IDs, metrics, and distributed tracing.
  • Add rate limits and abuse protection.
  • Publish preference-change events.
  • Add CI checks for build, typecheck, tests, Prisma validation, and Docker build.

About

Backend service for managing user notification preferences, regional policies, quiet hours, and delivery decision evaluation.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors