Skip to content

JhonSnakee/distributed-inventory-system

Repository files navigation

πŸ“¦ Distributed Inventory System

A backend prototype for a distributed inventory management system built with Node.js, Express and SQLite. It demonstrates key distributed systems concepts such as optimistic locking, idempotency, store-level partitioning and batch synchronization.


πŸš€ Features

  • Optimistic Locking β€” Version-based concurrency control to prevent lost updates in concurrent environments.
  • Idempotency β€” All write operations support Idempotency-Key header for safe retries on network failures.
  • Store-level Partitioning β€” Each SKU tracks inventory per store independently.
  • Batch Synchronization β€” Bulk push endpoint to reconcile inventory from multiple stores.
  • ACID Transactions β€” SQLite transactions ensure data integrity on all writes.
  • Centralized Error Handling β€” Structured JSON error responses with meaningful codes and timestamps.

πŸ› οΈ Tech Stack

Layer Technology
Runtime Node.js 18+
Framework Express.js
Database SQLite via better-sqlite3
Testing Jest + Supertest
Logging Morgan
ID Generation UUID v4

πŸ“ Project Structure

distributed-inventory-system/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ server.js               # Main application server & API routes
β”‚   └── error-handler.js        # Centralized error handling middleware
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ inventory.test.js       # Core API tests
β”‚   └── error-handling.test.js  # Error handling tests
β”œβ”€β”€ data/
β”‚   └── inventory.db            # SQLite database (auto-created on first run)
β”œβ”€β”€ scripts/
β”‚   └── simulate_concurrent_requests.py  # Concurrency simulation script
β”œβ”€β”€ api-design.md
β”œβ”€β”€ setup-instructions.md
β”œβ”€β”€ postman-examples.md
└── package.json

⚑ Getting Started

Prerequisites

  • Node.js 18+ and npm
  • Git (optional)

Installation

# Clone the repository
git clone <repository-url> distributed-inventory-system
cd distributed-inventory-system

# Install dependencies
npm install

Run the Server

npm start
# Server starts at http://localhost:3000

The SQLite database is created automatically at data/inventory.db and seeded with sample data on first run.


πŸ§ͺ Testing

# Run all tests
npm test

# Run with coverage report
npm run test:coverage

# Run in watch mode
npm run test:watch

🌐 API Reference

Base URL

http://localhost:3000

Headers

Header Description
X-Store-Id Identifies the store making the request
Idempotency-Key Unique key to ensure operation idempotency
Content-Type application/json (required for POST/PUT)

Endpoints

GET /health

Health check.

Response:

{ "status": "ok", "now": "2026-03-02T10:00:00.000Z" }

GET /inventory/:sku

Get aggregated inventory across all stores for a given SKU.

Response:

{
  "sku": "sku-123",
  "total": 15,
  "per_store": [
    { "store_id": "store-1", "quantity": 10, "version": 1, "last_updated": "..." },
    { "store_id": "store-2", "quantity": 5, "version": 1, "last_updated": "..." }
  ]
}

PUT /inventory/:sku

Set the quantity for a SKU in a specific store. Supports idempotency.

Headers: X-Store-Id, Idempotency-Key (optional)

Body:

{ "quantity": 15 }

Response:

{ "sku": "sku-123", "store_id": "store-1", "quantity": 15, "version": 2, "last_updated": "..." }

POST /inventory/:sku/adjust

Adjust inventory by a delta value using optimistic locking. The client must provide expectedVersion to prevent lost updates.

Headers: X-Store-Id, Idempotency-Key (optional)

Body:

{ "delta": -3, "expectedVersion": 1 }

Response:

{ "sku": "sku-123", "store_id": "store-1", "quantity": 7, "version": 2, "last_updated": "..." }

Error β€” Version Mismatch (409):

{ "error": "version_mismatch", "currentVersion": 3 }

Error β€” Insufficient Stock (400):

{ "error": "insufficient_stock" }

POST /sync/push

Batch synchronization β€” push multiple SKU quantities from a store to the central system. Supports idempotency.

Headers: Idempotency-Key (optional)

Body:

[
  { "sku": "sku-123", "quantity": 20, "store_id": "store-1" },
  { "sku": "sku-456", "quantity": 8,  "store_id": "store-1" }
]

Response:

{ "changed": [ { "sku": "sku-123", "store_id": "store-1", "quantity": 20, "version": 3, "last_updated": "..." } ] }

πŸ—οΈ Architecture & Design Decisions

Consistency over Availability

Critical stock operations prioritize strong consistency. When expectedVersion mismatches (concurrent update detected), the request is rejected with 409 Conflict so the client can re-fetch and retry with the latest version. This prevents overselling.

Optimistic Locking

Each inventory record carries a version field that increments on every write. Clients submit the expectedVersion they last read; if it no longer matches the database, the update is rejected.

Idempotency

Write operations (PUT, POST) accept an Idempotency-Key header. If the same key is seen again, the original response is returned immediately β€” enabling safe retries after network failures without side effects.

Store-level Partitioning

Each (sku, store_id) pair is tracked independently, supporting a distributed model where each physical store manages its own stock and syncs periodically to the central system.


πŸ”„ Concurrency Simulation

A Python script is provided to simulate concurrent requests and observe optimistic locking in action:

python scripts/simulate_concurrent_requests.py

πŸ“„ Additional Documentation

File Description
api-design.md API design decisions and endpoint overview
postman-examples.md Ready-to-use Postman request examples
setup-instructions.md Detailed setup and configuration guide
tech-stack.md Technology choices and GenAI integration
project-plan.md Project planning notes

πŸ‘€ Autor

Desarrollado con cariΓ±o por @JhonSnakee

About

A backend prototype for a distributed inventory management system built with Node.js, Express and SQLite. It demonstrates key distributed systems concepts such as optimistic locking, idempotency, store-level partitioning and batch synchronization.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors