# Performance & Stability Notes

This document captures a quick, security-light performance read on the current local setup. Focus is on responsiveness, throughput, and operational weak spots rather than external attack surface.

## Stack Snapshot
- Express + Mongoose (v5) with compression, JSON body parsing, cookies, and dev logging via morgan.
- Routers mounted under `/api/v1/*`; static assets served from `/uploads`.
- Local MongoDB connection via `DATABASE_LOCAL`; envs loaded from `config.env`.
- Image handling present via `multer` and `sharp` (see `uploads/` and `utils/imageproccessor.js`).

## Current Strengths
- HTTP compression enabled by default, reducing payload sizes for responses.
- CORS configured to allow expected local origins and Cloudflare tunnels, easing local dev flows.
- Centralized error handler in place, which simplifies response shaping under load.
- Directory bootstrap for uploads at start-up prevents runtime failures when writing files.

## Performance Weaknesses (Ignoring Security)
- Mongoose v5 lacks newer perf improvements (bulk writes, faster change streams, better typings); upgrading to v7+ would help latency and connection handling.
- Request logging (`morgan` in `dev` mode) runs on every request; disable in production-like runs to avoid I/O overhead.
- All routes share a single Express instance with no clustering; CPU-bound tasks will bottleneck on one core.
- No caching layer (in-memory or HTTP) for hot reads (e.g., product/category lists); repeated hits will always query MongoDB.
- Upload and image processing likely synchronous per request; heavy image operations can slow concurrent requests if not offloaded to a worker queue.
- No response size limits or body size tuning; large payloads can increase memory use and GC pressure.

## Quick Wins for Local Performance
- Run with `NODE_ENV=production` to disable dev-only overhead (morgan, extra logs) and let Express skip some work.
- Add `compression` conditionally (or tune thresholds) if CPU is a bottleneck and responses are already small.
- Enable lean queries (`.lean()`) on read-heavy endpoints to skip Mongoose doc hydration.
- Add MongoDB indexes on frequently filtered fields (products, orders, users) to reduce query time; verify with `db.collection.getIndexes()`.
- For image uploads, resize/optimize in a background worker (BullMQ or node worker threads) to keep request latency low.
- Consider simple in-memory caching (e.g., LRU) for read-only endpoints; invalidate on writes.

## Observed Operational Risks
- App boot fails if `DATABASE_LOCAL` is unset; add a fallback or clearer console guidance.
- If MongoDB is slow/unavailable, requests will stack because there is no circuit breaker or timeout logic on queries.
- CORS rejection throws errors for unexpected origins; during perf testing, set `origin: true` or expand the allowed list to avoid noisy failures.

## Suggested Benchmarks
- Smoke: `npm start`, hit `/api/v1/product` (list) and `/api/v1/orders` (list) with 50–100 rps for 1 minute; record p50/p95 latency and error rate.
- Upload path: send 5–10 concurrent image uploads to the product endpoint; measure time-to-first-byte and total time.
- Memory watch: run a 10-minute constant load (30–50 rps mix of reads/writes); observe RSS growth to spot leaks.

## Minimal Test/Run Commands
- Start local: `npm install` then `npm start` (requires MongoDB running and `config.env`).
- Tests: `npm test` (Jest). Use this to ensure refactors for performance do not break behavior.

## .lean() Implementation Status ✅
The following read-only queries have been optimized with `.lean()`:
- `Product.find()` - list products (getAllProducts)
- `Product.find()` - expired products check
- `Order.find()` - list orders (already had .lean())
- `Bill.find()` - list bills (getAllBills and getAllBillsRaw)
- `Bill.find()` - recent transactions
- `Category.find()` - list categories
- `CashIn/CashOut.find()` - list cash in/out (already had .lean())
- Generic factory handlers: `getAll()` and `findOne()` now use `.lean()`

**Note:** `User.findById()` in auth controller intentionally excludes `.lean()` since the protection middleware needs full document methods like `changedPasswordAfter()`.

## Prioritized Next Steps (Perf Focus)
1) Add indexes for top query patterns (products/categories/orders filters).
2) Gate morgan/compression behind env flags for prod-like runs.
3) Introduce simple caching for hottest read endpoints; clear on writes.
4) Offload image processing to background work; keep API responses fast.
5) Monitor memory usage and query performance with `.lean()` in place.
