Skip to content

Repository files navigation

Notification Service

A production-oriented notification delivery service that currently supports Telegram as its delivery channel.

It keeps notification-delivery complexity out of application services, focusing on reliable processing, controlled throughput, and predictable delivery for individual and bulk workloads.

Highlights

  • Queue-based delivery: Redis and BullMQ power separate staging and delivery queues for each service, keeping API requests fast and notification processing isolated.
  • Flexible scheduling: priority levels, recipient timezones, and configurable delivery windows control when notifications are sent.
  • Responsible rate limiting: service-wide and per-recipient limits provide backpressure, while Telegram 429 responses pause and reschedule affected work automatically.
  • Resilient sending: transient network and Telegram server failures are retried, blocked recipients are cached, and delivery outcomes are persisted with structured error details.
  • Secure service integration: versioned API tokens support credential revocation, and Telegram bot credentials are encrypted before database storage.

Architecture

Notification delivery architecture

PostgreSQL stores notifications and service credentials, while Redis and BullMQ provide the queues used for asynchronous processing. New notifications wait in the staging queue until the scheduler determines that their delivery window and rate limits allow them to be sent. The scheduler then moves them to a priority queue, where a notification worker picks them up, sends them through Telegram, and records the outcome in PostgreSQL.

Built with TypeScript, Fastify, PostgreSQL, Prisma, Redis, BullMQ, React, and Docker.

Getting Started From Scratch

1. Install Dependencies

Install backend dependencies from the repository root:

npm install

Install admin UI dependencies:

cd admin
npm install
cd ..

2. Create Env Files

Copy the examples:

cp .env.example .env
cp admin/.env.example admin/.env

Fill root .env values:

Variable Where to get it
POSTGRES_URL Local development can use the value from .env. npm run dev reads it and starts a matching Docker Postgres container.
REDIS_URL Local development can use the value from .env. npm run dev reads it and starts a matching Docker Redis container.
PORT Choose the local backend port. The example uses 8080.
APP_ENV Use development locally. Use production only for deployed environments.
BASIC_AUTH_USER Choose a username for the admin UI and API docs. The example uses admin.
BASIC_AUTH_PASSWORD Choose a password for the admin UI and API docs. The example uses admin.
AUTH_TOKEN_PRIVATE_KEY Generate a base64 secret, for example openssl rand -base64 32. This signs service API tokens.
DB_ENCRYPTION_PRIVATE_KEY Generate a base64 32-byte secret, for example openssl rand -base64 32. This encrypts service credentials in the database.
LOAD_TESTING_TELEGRAM_API_URL Leave commented unless running local load tests with the Telegram mock server. It is allowed only when APP_ENV=development.

Fill admin/.env values:

Variable Where to get it
VITE_API_URL API base URL used by admin UI requests. Use / for local development so requests go through the Vite proxy.
VITE_BASE_PATH Browser router base path for the admin UI. Use /admin for local development because the backend serves the built admin UI at this path.
ADMIN_API_PROXY_TARGET Set it to the backend origin (host plus the PORT from the root .env), without an /api path. For example, use http://localhost:8080 when PORT=8080.

When creating services through the admin UI, you will also need a Telegram bot token from BotFather.

3. Start Postgres And Redis

Start only the Docker-backed local services for the initial Prisma setup:

npm run dev -- --no-server

Keep this process running while you generate Prisma code and sync the database.

4. Generate Prisma Client And Sync The Database

In another terminal, run:

npm run prisma:update:dev

This runs prisma generate && prisma db push, which generates the Prisma client under src/database/generated and applies the schema to the local database.

5. Start The Project

After Prisma setup is complete, stop the npm run dev -- --no-server process from step 3. Then start Postgres, Redis, and the backend watcher together:

npm run dev

The API is available on the port configured by PORT.

6. Start The Admin UI

In another terminal:

cd admin
npm run dev

The admin dev server proxies /api requests to http://localhost:8080 by default. Use the BASIC_AUTH_USER and BASIC_AUTH_PASSWORD values from .env when prompted by protected backend routes.

Useful Commands

Repository commands:

  • npm run admin:api:generate: exports the backend OpenAPI document to the ignored admin/openapi.json file and regenerates the admin API client from it.

Backend commands:

  • npm run dev: starts Docker-backed Postgres/Redis and the backend watcher.
  • npm run dev:server: starts only the backend watcher.
  • npm run prisma:update:dev: regenerates Prisma client and pushes the schema to the configured database.
  • npm run prisma:migrate: applies existing Prisma migrations.
  • npm run typecheck: runs TypeScript without emitting files.
  • npm run build: builds the backend into dist/.
  • npm start: runs the built backend from dist/main.js.

Admin commands:

  • npm run dev: starts the admin UI dev server.
  • npm run build: builds the admin UI.
  • npm run start: previews the built admin UI through Vite.
  • npm run api:generate: regenerates the client from admin/openapi.json.

API Documentation

Start the backend and open:

http://localhost:8080/api/v1/docs

The API documentation is protected with basic auth. Use BASIC_AUTH_USER and BASIC_AUTH_PASSWORD from .env.

About

A production-oriented notification delivery service

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages