# Node.js + Express + MongoDB — AI Agent Guidelines & Architecture Rules

> Production guidelines for Express REST APIs, Mongoose schema design, and MongoDB indexing/transaction discipline.
> Technologies: Node.js, Express, MongoDB, TypeScript, Redis

---

## AGENTS.md
```markdown
# Project Architecture & Guidelines (Node.js + Express + MongoDB)

## 1. System Architecture
- **Runtime**: Node.js (TypeScript, `ts-node`/`tsx` for dev, compiled output for production).
- **Web Framework**: Express 4/5 for REST API routing and middleware.
- **Database**: MongoDB with Mongoose for schema definition, validation, and typed models.
- **Caching/Queues**: Redis for session storage, caching, and BullMQ-backed background jobs.

## 2. Mongoose Schema & Validation
- Define explicit schemas with Mongoose (`new Schema({...}, { timestamps: true })`) even though MongoDB is schemaless at the database level — untyped documents are the single largest source of bugs in Node/Mongo codebases.
- Use Mongoose's built-in validators (`required`, `enum`, custom `validate` functions) as the first line of defense; add a Zod schema at the API boundary for request-shape validation before it reaches Mongoose.
- Prefer embedding for data that's always read together and rarely grows unbounded (a project's settings object); reference (`ObjectId` + `ref`) for data that's queried independently or grows without bound (a project's activity log).

## 3. Indexing & Query Discipline
- Every field used in a `find()` filter, sort, or unique constraint needs an explicit index (`schema.index({ projectId: 1, createdAt: -1 })`) — MongoDB does not warn about missing indexes, it just degrades to a full collection scan.
- Use `.lean()` on read-only queries that don't need Mongoose document methods; it skips hydration overhead and meaningfully reduces memory/CPU on hot read paths.
- Avoid unbounded `.find({})` without pagination (`.limit()`/`.skip()` or cursor-based pagination) on any collection that can grow past a few thousand documents.

## 4. Transactions & Data Consistency
- Use MongoDB multi-document transactions (`session.startTransaction()`) for any write that spans more than one collection and must be atomic (e.g. deducting credits and creating a record) — MongoDB supports ACID transactions on replica sets, this isn't a "NoSQL means no transactions" situation.
- Transactions require a replica set (even a single-node one in development); configure this explicitly rather than discovering it's missing when a transaction call throws in production.

## 5. Common Pitfalls / Coding Standards
- ❌ Querying without an index on a collection expected to grow — profile with `.explain('executionStats')` before shipping a new query pattern.
- ❌ Deeply nested embedded arrays that grow unbounded (MongoDB documents have a 16MB size limit).
- ✅ Use `.lean()` for read-heavy endpoints; reserve hydrated Mongoose documents for paths that call instance methods or need change tracking.

## 6. Testing Conventions
- Vitest/Jest with `mongodb-memory-server` for fast, isolated integration tests against a real (in-memory) MongoDB instance rather than mocking Mongoose.
- Supertest for Express route-level tests, asserting status codes and response shape.
- Test index usage explicitly for any query on a collection expected to scale, via `.explain()` assertions in CI if query performance regressions have happened before.

## 7. Git Workflow & PR Conventions
- Conventional Commits scoped to the resource, e.g. `perf(projects): add compound index for owner+status filter`.
- New indexes ship in the same PR as the query pattern that needs them, with a migration/init script that creates them idempotently (`createIndexes` is safe to re-run).
- Require `tsc --noEmit` and the test suite green before merge.
- Squash-merge; run index creation as an explicit deploy step on large collections (it can lock or slow the collection during build).
```

---

## CLAUDE.md
```markdown
# CLAUDE.md — Node.js + Express + MongoDB

Refer to @AGENTS.md for complete database configuration and architectural constraints.

## Common Commands
- `bun run dev` - Start local Express development server
- `bun run build` - Compile TypeScript to production output
- `bun run test` - Run the Vitest/Jest suite (with mongodb-memory-server)
- `docker compose up mongo redis` - Start local MongoDB + Redis

## Claude Specific Directives
- Always add an explicit Mongoose schema and index for any new query pattern; MongoDB does not warn about missing indexes.
- Use `.lean()` on read-only queries that don't need Mongoose document methods.
```

---

## .cursor/rules/stack.mdc
```markdown
---
description: Node.js + Express + MongoDB architecture rules
globs: ["**/*.ts"]
alwaysApply: true
---

# Node.js + Express + MongoDB

- Express REST API in TypeScript; Mongoose schemas with explicit validators even though MongoDB itself is schemaless.
- Every filter/sort/unique field needs an explicit index -- MongoDB silently full-scans instead of warning.
- Use `.lean()` on read-only queries; reserve hydrated documents for paths needing instance methods or change tracking.
- Multi-collection atomic writes use MongoDB transactions (`session.startTransaction()`) on a replica set, not ad hoc sequential writes.
- Embed data that's always read together and bounded in size; reference data that's queried independently or grows unbounded.
- Zod validation at the API boundary before Mongoose validators run.
```

---

## Architecture Overview & Best Practices
## Architecture Overview

Standardized production guidelines for **Node.js**, **Express**, and **MongoDB** via **Mongoose** — the default choice when a project's data is naturally document-shaped (chat messages, notification payloads, flexible per-tenant configuration) rather than relational.

### Verified Real-World Adoption

**LibreChat** (multi-model AI chat workspace) and **Novu** (notification infrastructure) both run Node.js/TypeScript + MongoDB in production, and **Rocket.Chat** uses the same combination for its real-time team communications platform.

### Key Architectural Nuances

- **Schemas Matter Even on a Schemaless Database**: Mongoose schemas plus a Zod boundary layer are what actually prevent the "any shape of document can end up in this collection" failure mode that gives MongoDB its reputation for bugs.
- **Indexes Are Opt-In, Not Automatic**: Unlike a well-tuned PostgreSQL setup that at least logs slow queries, MongoDB will silently full-scan an unindexed filter forever — index discipline has to be deliberate, not reactive.