A robust, multi-tenant inventory management REST API built with Node.js, Express, TypeScript, and Prisma.
The system supports multiple shops, each with independent inventory tracking, customer orders, and purchase orders.
With Redis caching, p95 latency is reduced by 74%, and full system reliability is ensured with 95% test coverage.
- Features
- Prerequisites
- Getting Started
- Local Setup (without Docker)
- Scripts
- Testing
- Benchmarks
- API Documentation
- Technologies Used
- Scalability Considerations
- Multi-Tenant Architecture: Support for multiple shops, each with isolated inventory and order management.
- Modular Design: Feature-based organization (Auth, Admin, Shop, Products, Suppliers, Customer Orders, Purchase Orders).
- Per-Shop Inventory: Products maintain separate stock levels per shop with automatic low-stock detection.
- Type Safety: Built with TypeScript and Zod for runtime request validation.
- JWT Authentication: Secure API access with JSON Web Token-based authentication.
- Database ORM: Prisma with PostgreSQL for type-safe database access.
- Docker Support: Containerized setup with Docker Compose for easy deployment.
- Comprehensive Testing: Integration and unit tests with Vitest and Supertest.
- 95% Test Coverage: Extensive coverage across all modules for high reliability.
- Structured Logging: Request logging with Pino.
- Code Quality: Linting and formatting with Biome.
- Performance Testing: Load testing with k6.
- Docker — the recommended way to run the project. No other dependencies needed.
If running without Docker:
- Node.js (v20 or higher)
- PostgreSQL database
The quickest way to run the project is with Docker.
-
Clone the repository:
git clone https://github.com/Youssef-codin/inventory-management-api cd inventoryManagement -
Configure Environment Variables: Create a
.envfile in the root directory:Variable Description Example PORTPort the server listens on 3000DATABASE_URLPostgreSQL connection string postgresql://yourUser:yourPassword@localhost:5432/inventory_db?schema=publicJWT_SECRETSecret key for signing JWT tokens your-secret-keyREDIS_URLRedis connection string redis://:yourPassword@localhost:6380
Note:
When running inside Docker, useredis://:password@redis:6379(internal network).
When running locally on the host, useredis://:password@localhost:6380(exposed port).
-
Start the containers:
docker compose up
This will start both the API server on port
3000, a PostgreSQL instance on port5433, and Redis on port6380.
If you prefer to run without Docker, make sure you have Node.js and PostgreSQL installed.
-
Install dependencies:
npm install
-
Database Setup: Run the migrations to set up your database tables:
npm run migrate init
Generate the Prisma client:
npm run generate
-
Seed the Database (optional): Populate the database with demo data (admin user, shops, suppliers, products, orders):
# Small dataset (~5 products, 2 shops, 2 suppliers) npm run seed # Large dataset (~1000 products, 10 shops, 50 suppliers, 150 orders) - for load testing npm run seed:large
-
Run the Application:
npm run dev
| Script | Description |
|---|---|
npm run dev |
Start the development server with file watching and .env loading |
npm run start |
Build and start the production server |
npm run type-check |
Run the TypeScript compiler to check for type errors |
npm run migrate <name> |
Run Prisma migrations with a descriptive name |
npm run generate |
Generate the Prisma Client from schema.prisma |
npm run seed |
Clear the database and seed it with demo data (~5 products) |
npm run seed:large |
Clear the database and seed it with large dataset (~1000 products) |
npm run studio |
Open Prisma Studio, a visual database editor |
npm test |
Run integration and unit tests with Vitest |
npm run test:coverage |
Run tests and generate a code coverage report |
npm run lint |
Lint and format the codebase using Biome |
npm run lint:fix |
Automatically fix linting and formatting issues |
Tests are organized per-module with both integration and unit tests:
# Run all tests
npm test
# Run with coverage report
npm run test:coverageCoverage Summary:
The project maintains 95% test coverage, ensuring that core logic, services, and API routes are thoroughly verified through automated testing.
Run the performance tests:
# Test full system (includes list, search, create operations)
k6 run tests/perf/load.test.js
# Test cached endpoints only
k6 run tests/perf/cache-benchmark.test.jsBy default, tests connect to http://localhost:3000. Override with:
k6 run tests/perf/load.test.js -e BASE_URL=http://your-server:3000Reproducing the benchmarks:
# 1. Seed the large dataset
npm run seed:large
# 2. Test WITHOUT Redis - comment out initRedis() in src/app.ts, then start server:
docker compose up -d
# 3. Run the baseline test
k6 run --summary-export=docs/baseline.json tests/perf/cache-benchmark.test.js
# 4. Test WITH Redis - uncomment initRedis(), restart server:
docker compose restart
# 5. Run the Redis test
k6 run --summary-export=docs/redis.json tests/perf/cache-benchmark.test.jsTo test without Redis caching, comment out the initRedis() call in src/app.ts.
Load tested with k6 using 100 VUs over 55 seconds (15s ramp-up → 30s steady → 10s ramp-down).
Tests run locally with Docker against a dataset of 1000 products, 10 shops, and 50 suppliers.
| Metric | Without Redis | With Redis | Difference |
|---|---|---|---|
| Avg Latency | 3.50 ms | 1.06 ms | 69.7% faster |
| p95 Latency | 9.14 ms | 2.37 ms | 74.1% faster |
| Throughput | 450.54 req/s | 454.33 req/s | 0.8% higher |
| Total Requests | 24,848 | 25,071 | +223 |
| Passes | 24,843 | 25,066 | +223 |
Key Improvements:
- 69.7% reduction in average response time (3.50ms → 1.06ms)
- 74.1% reduction in p95 latency (9.14ms → 2.37ms)
Cached Endpoints:
GET /product/:id— Product lookupsGET /product— Product listingsGET /product/low-stock— Low stock alertsGET /product/search— Product searchGET /shop/:id— Shop lookupsGET /supplier/:id— Supplier lookupsGET /customer-order/:id— Customer order lookupsGET /purchase-order/:id— Purchase order lookups
Cache is automatically invalidated on create/update/delete operations.
The API achieves 95% overall test coverage, verified through integration and unit testing with Vitest and Supertest.
This ensures strong reliability across all modules—authentication, inventory, orders, and supplier management—with both logic and data-layer interactions thoroughly tested.
The full OpenAPI specification is available in the docs/ directory:
- OpenAPI Specification — Use with Swagger UI or Postman to explore all endpoints.
| Category | Technology |
|---|---|
| Runtime | Node.js |
| Framework | Express.js |
| Language | TypeScript |
| ORM | Prisma |
| Database | PostgreSQL |
| Validation | Zod |
| Auth | JSON Web Tokens |
| Logging | Pino |
| Testing | Vitest, Supertest, k6 |
| Linting | Biome |
| Containers | Docker |
- Redis caching reduces database load and tail latency (~74% p95 improvement).
- Database indexed on primary and foreign keys for fast lookups.
- Stateless API with JWT auth enables horizontal scaling.
- Cache invalidation on write operations ensures data consistency.
- High test coverage (95%) improves maintainability and refactor safety.