Novu is an open-source notification and agent-communication infrastructure platform built as a TypeScript Nx monorepo, with independent NestJS services for its API, worker, websocket, webhook, and inbound-mail apps backed by MongoDB and a BullMQ-based job queue.
- Language
- TypeScript
- Database
- MongoDB
- Hosting
- Docker
- Running for
- 2 years 9 months
- Team
- 6-20 people
Why this architecture
Delivery concerns are split into separately deployable NestJS services (api, worker, ws, webhook, inbound-mail) sharing one Mongoose-based data-access library, so notification ingestion, queued processing, and realtime delivery can each be scaled and released on their own schedule inside a single Nx-managed workspace.
Tech stack by layer
9 technologies · audited Sep 17, 2026- LangChainUsed by the dashboard for LangGraph-based agent chat features.(inferred)
Novu architecture diagram
Open SVGDiagram as text
- Dashboard (React · Vite) → api (NestJS REST): REST
- Inbox & SDKs (JS · React) → api (NestJS REST): REST
- Inbox & SDKs (JS · React) → ws (Socket.IO): realtime
- api (NestJS REST) → MongoDB (Mongoose (dal)): dal
- api (NestJS REST) → Redis (BullMQ · adapter): enqueue
- Redis (BullMQ · adapter) → worker (workflow jobs): jobs
- worker (workflow jobs) → MongoDB (Mongoose (dal)): dal
- ws (Socket.IO) → Redis (BullMQ · adapter): Socket.IO adapter
- webhook (NestJS) → MongoDB (Mongoose (dal)): dal
Key architectural decisions
6 decisions- 01
Each runtime concern is a separate NestJS application under apps/
apps/api, apps/worker, apps/ws, apps/webhook, and apps/inbound-mail each have their own package.json and Dockerfile (for example apps/worker/package.json and apps/ws/package.json), so the REST API, job processing, websocket delivery, inbound webhooks, and inbound email parsing scale and deploy independently.
- 02
MongoDB access is centralized in a shared dal library
libs/dal/package.json depends on mongoose and mongoose-delete and is consumed as a workspace package (@novu/dal) by apps/worker, apps/ws, and apps/webhook, so schema and query logic for MongoDB lives in one place instead of being duplicated per service.
- 03
Enterprise queueing uses a private BullMQ Pro fork installed at build time
apps/api/Dockerfile conditionally installs @taskforcesh/bullmq-pro during the Docker deploy stage when a BULL_MQ_PRO_NPM_TOKEN secret is present, layering the paid BullMQ Pro package on top of the open-source build rather than requiring it as a hard dependency.
- 04
The dashboard is a standalone Vite/React app, not server-rendered
apps/dashboard/package.json builds with vite build and serves static output via http-server for the start:static:build script, and end-to-end tests run against it with Playwright (test:e2e in the same file).
- 05
Nx task graph replaces per-package build scripts for cross-cutting tasks
The root package.json defines nx build @novu/api-service, nx run-many --target=build --all --projects=tag:type:package, and similar Nx-driven commands, with nx.json (trimmed in the audited facts but present at the repository root) configuring the project graph and task caching.
- 06
Agent-facing surfaces get a dedicated workspace area
The repository root contains libs/agent-evals and packages/agent-toolkit and packages/agent-event-protocol directories alongside the notification-delivery apps, and apps/dashboard/package.json depends on @langchain/langgraph-sdk and @assistant-ui/react for in-product agent chat.
How Novu is built
How Novu is structured
Novu's default branch, next, is organized as an Nx-managed pnpm workspace. Runtime services live under apps/: apps/api (the REST API service), apps/worker (job processing), apps/ws (websocket delivery), apps/webhook (inbound webhook handling), apps/inbound-mail (inbound email parsing), and apps/dashboard (the React admin UI). Shared code lives under libs/, including libs/dal (data access), libs/application-generic, libs/notifications, and libs/automation. Client-facing SDKs and adapters are published from packages/, covering packages/js, packages/react, packages/react-native, packages/framework, and channel-specific adapters like packages/chat-adapter-web-chat and packages/chat-adapter-email. An enterprise/ directory holds additional packages and workers (enterprise/workers/socket, enterprise/workers/step-resolver, enterprise/workers/thalamus-observer) that extend the open-source services. The workspace root also contains libs/agent-evals, packages/agent-toolkit, and packages/agent-event-protocol, directories that sit alongside the notification-delivery apps rather than inside them; combined with the dashboard's @langchain/langgraph-sdk and @assistant-ui/react dependencies, this shows Novu's product surface extends past notification delivery into agent-facing chat and tool-use scenarios, tracked as first-class workspace packages.
Frontend
apps/dashboard/package.json describes a Vite-based React application ("start": "vite", "build": "... vite build") rather than a server-rendered framework. It integrates authentication through @clerk/react and @better-auth/sso, code editing via CodeMirror (@codemirror/lang-html, @codemirror/lang-liquid), and agent-facing chat UI through @assistant-ui/react and @langchain/langgraph-sdk. End-to-end tests run with Playwright (test:e2e, test:e2e:codegen scripts in the same file), and the dashboard can also be served as a static build via http-server for the start:static:build script. Beyond the dashboard, the packages/ directory publishes the notification-facing client SDKs that customers embed in their own products: packages/js (a framework-agnostic in-app inbox widget), packages/react and packages/react-native (framework wrappers around it), and packages/framework (the code-first notification workflow SDK used outside the dashboard entirely).
Backend & APIs
Each backend service is an independent NestJS application. apps/worker/package.json depends on @nestjs/common, @nestjs/core, and workspace libraries @novu/application-generic, @novu/dal, @novu/framework, @novu/shared, and @novu/stateless. apps/ws/package.json adds @nestjs/platform-socket.io, @nestjs/websockets, and @socket.io/redis-adapter for realtime delivery, plus @socket.io/admin-ui for operational visibility. apps/webhook/package.json is a slimmer NestJS app focused on inbound webhook handling, depending on the same @novu/dal and @novu/shared libraries. All of the backend apps share Sentry instrumentation (@sentry/nestjs, @sentry/node, @sentry/profiling-node) and are built with biome for linting and formatting rather than ESLint/Prettier.
Data & persistence
libs/dal/package.json (the @novu/dal package) is the shared data-access library, depending on mongoose and mongoose-delete for MongoDB access, plus @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner for attachment storage. This library is consumed as a workspace dependency by apps/worker, apps/ws, and apps/webhook, keeping schema definitions and queries in one place rather than duplicated per service. Job queuing runs through a BullMQ-family queue: apps/api/Dockerfile's deploy stage conditionally installs @taskforcesh/bullmq-pro@6.11.0 from a private registry (npm.taskforce.sh) when a BULL_MQ_PRO_NPM_TOKEN build secret is supplied, layering the commercial BullMQ Pro package on top of the open-source build.
Build, test & deploy
The root package.json defines Nx-driven build commands such as nx build @novu/api-service, nx build @novu/dashboard, and nx run-many --target=build --all --projects=tag:type:package, with pnpm@11.0.9 pinned as the package manager. Each service Dockerfile (apps/api/Dockerfile, apps/worker/Dockerfile, apps/ws/Dockerfile, apps/webhook/Dockerfile, apps/inbound-mail/Dockerfile) follows a similar multi-stage pattern: a node:22.23-alpine3.23 base installs pm2 and pnpm globally, copies workspace metadata and dependency manifests separately from source (./meta, ./deps, ./pkg) to maximize Docker layer caching, then runs a service-specific nx build command before a final deploy stage that uses pnpm --filter <package> deploy --legacy --prod. Backend tests run with Mocha (apps/worker and apps/ws both use mocha --timeout 10000 --require ts-node/register) rather than Jest.
Self-hosting notes
Because each runtime concern (api, worker, ws, webhook, inbound-mail) has its own docker:build and docker:build:depot scripts and Dockerfile, self-hosters can build and scale these services independently rather than deploying a single monolithic container. The BullMQ Pro install step in apps/api/Dockerfile is guarded by an optional BULL_MQ_PRO_NPM_TOKEN secret, so a self-hosted build without that token falls back to the open-source queue path instead of failing.
Sources & repo audit
- Audited
- Sep 17, 2026
- Commit
- a0b5e2d
- License
- NOASSERTION
- apps/worker/package.json (NestJS worker depending on @novu/dal, @novu/framework)
- apps/ws/package.json (NestJS + Socket.IO + Redis adapter)
- libs/dal/package.json (Mongoose data-access library)
- apps/api/Dockerfile (multi-stage build, conditional BullMQ Pro install)
- apps/dashboard/package.json (Vite/React dashboard)
Independent analysis of repository at github.com/novuhq/novu. Spotted an inaccuracy? Use the claim form to request a correction.
Show this stack on your README or website
[](https://stackitfast.com/project/novu)Paste it into your README. It shows your current stack and links to this page.
Scaffold it with your agent
Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Novu's architecture.
- 1Copy the promptThe full markdown spec, with every layer and decision.
- 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
- 3Paste and scaffoldUse it as the first instruction; review before you ship.
# MISSION: Scaffold "Novu" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Novu**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Novu
- **What It Does**: Novu is an open-source notification and agent-communication infrastructure platform built as a TypeScript Nx monorepo, with independent NestJS services for its API, worker, websocket, webhook, and inbound-mail apps backed by MongoDB and a BullMQ-based job queue.
- **Domain & Category**: Notification Infra
- **Production Scale**: 6-20 people
- **Development Mode**: HYBRID
- **Architectural Rationale**: Delivery concerns are split into separately deployable NestJS services (api, worker, ws, webhook, inbound-mail) sharing one Mongoose-based data-access library, so notification ingestion, queued processing, and realtime delivery can each be scaled and released on their own schedule inside a single Nx-managed workspace.
- **Live Website Reference**: https://novu.co
- **Source Repository**: https://github.com/novuhq/novu
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: TypeScript, React, NestJS, MongoDB, Redis, BullMQ, Socket.IO, Nx, Docker
- **Primary Language(s)**: TypeScript, JavaScript, Python
- **License of the reference repo**: NOASSERTION
- **Frontend**: React — Builds the dashboard app with Vite.; Vite — Bundles and serves the dashboard application.
- **Backend & APIs**: NestJS — Implements the api, worker, ws, webhook, and inbound-mail services as separate NestJS apps.; Socket.IO — Powers the ws app, which pushes realtime in-app notifications to connected clients.
- **Data & persistence**: MongoDB — Primary datastore, accessed through Mongoose models in the shared dal library.; Redis — Backs the queue adapter used between the api, worker, and ws services.; BullMQ — Job queue for workflow execution, referenced via the BullMQ Pro fork installed at Docker build time.
- **Infrastructure & deploy**: Nx — Orchestrates builds and task dependencies across the apps/ and libs/ workspace.; Docker — Each service (api, worker, ws, webhook, inbound-mail) has its own multi-stage Dockerfile.; pnpm — Package manager for the Nx workspace.
- **Tooling, testing & ops**: LangChain — Used by the dashboard for LangGraph-based agent chat features.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/novuhq/novu @ a0b5e2d)
1. **Each runtime concern is a separate NestJS application under apps/**: apps/api, apps/worker, apps/ws, apps/webhook, and apps/inbound-mail each have their own package.json and Dockerfile (for example apps/worker/package.json and apps/ws/package.json), so the REST API, job processing, websocket delivery, inbound webhooks, and inbound email parsing scale and deploy independently.
2. **MongoDB access is centralized in a shared dal library**: libs/dal/package.json depends on mongoose and mongoose-delete and is consumed as a workspace package (@novu/dal) by apps/worker, apps/ws, and apps/webhook, so schema and query logic for MongoDB lives in one place instead of being duplicated per service.
3. **Enterprise queueing uses a private BullMQ Pro fork installed at build time**: apps/api/Dockerfile conditionally installs @taskforcesh/bullmq-pro during the Docker deploy stage when a BULL_MQ_PRO_NPM_TOKEN secret is present, layering the paid BullMQ Pro package on top of the open-source build rather than requiring it as a hard dependency.
4. **The dashboard is a standalone Vite/React app, not server-rendered**: apps/dashboard/package.json builds with vite build and serves static output via http-server for the start:static:build script, and end-to-end tests run against it with Playwright (test:e2e in the same file).
5. **Nx task graph replaces per-package build scripts for cross-cutting tasks**: The root package.json defines nx build @novu/api-service, nx run-many --target=build --all --projects=tag:type:package, and similar Nx-driven commands, with nx.json (trimmed in the audited facts but present at the repository root) configuring the project graph and task caching.
6. **Agent-facing surfaces get a dedicated workspace area**: The repository root contains libs/agent-evals and packages/agent-toolkit and packages/agent-event-protocol directories alongside the notification-delivery apps, and apps/dashboard/package.json depends on @langchain/langgraph-sdk and @assistant-ui/react for in-product agent chat.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
- Structure as a Turborepo monorepo with strict package boundaries:
- `apps/web`: Application UI, routing, layouts, and server endpoints.
- `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
- `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
- `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
- Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
- Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
- Isolate interactive UI state to leaf components. Keep core pages lightweight and performant.
4. **Design System & Aesthetics**:
- Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
- Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
- Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
- Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer (MongoDB, Redis, BullMQ): client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.Frequently asked about Novu
What tech stack does Novu use?
Novu is a TypeScript Nx monorepo with separate NestJS services for its API, worker, websocket, webhook, and inbound-mail apps (apps/*), a MongoDB datastore accessed through a shared Mongoose-based dal library, and a Vite/React dashboard.
Does Novu use MongoDB or a SQL database?
MongoDB. libs/dal/package.json depends on mongoose and mongoose-delete, and this library is the shared data-access layer consumed by the worker, ws, and webhook NestJS apps.
How does Novu process notification jobs?
Through a BullMQ-based queue; apps/api/Dockerfile shows the build conditionally installing the commercial @taskforcesh/bullmq-pro package when a token secret is supplied, layered on top of the open-source queue setup.
Can Novu be self-hosted with Docker?
Yes, each service under apps/ (api, worker, ws, webhook, inbound-mail) ships its own Dockerfile with docker:build and docker:build:depot scripts for building that service independently.
One email a month: new deep dives and stack trends
New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.
Similar architectures
- ToolJetHybridLow-Code Developer Tool Platform · 6-20 peopleShares TypeScript · React · NestJS
- Cal.comClassicScheduling SaaS · 6-20 peopleShares TypeScript · React · NestJS
- ExcalidrawClassicCanvas Editor · 2-5 peopleShares React · TypeScript · Socket.IO
- HoppscotchClassicAPI Testing Client · 6-20 peopleShares TypeScript · NestJS · Redis
- NocoDBHybridSmart Database Spreadsheet · 6-20 peopleShares TypeScript · NestJS · Redis
- PrismaClassicNext-Generation Node.js & TypeScript ORM · 1M+ MAUShares TypeScript · MongoDB · Docker