A high-concurrency inventory management system built for the Techzu Ichicode technical assessment. Users reserve limited-edition sneakers in real time, complete purchases within a 60-second window, and see live stock updates across all connected clients.
| URL | |
|---|---|
| Frontend | <frontend-url> |
| Backend | <backend-url> |
| Video Walkthrough | <loom-video-link> |
git clone https://github.com/Code5linger/techzu.backend.git
cd techzu.backendnpm installCreate a .env file in the project root:
PORT=5000
DATABASE_URL=postgresql://neondb_owner:<---your-id>@<---your-password>.c-2.ap-southeast-1.aws.neon.tech/neondb?sslmode=verify-full&channel_binding=require
NODE_ENV=development
ALLOWED_ORIGINS=https://techzu-frontend.vercel.app,https://techzu-frontend-p29fe7h8v-codeslingers-projects.vercel.app, http://localhost:5173, http://localhost:5174Create a PostgreSQL database named techzu.
Seed the database with sample data:
npm run seednpm run devThe API will be available at:
http://localhost:5000
- Real-time stock updates. All connected clients see inventory changes instantly via WebSocket
- Atomic reservation. Concurrent requests are handled at the database level; overselling is impossible
- 60-second purchase window. Reservations expire automatically, releasing stock back to inventory
- Activity feed. The 3 most recent purchasers are shown per drop, updated live
- User registration. Enter a username to access drops; identity persists across page reloads
| React 19 + Vite | UI framework and build tool |
| TypeScript | Type safety |
| Tailwind CSS v4 | Styling (via @tailwindcss/vite plugin, no PostCSS config) |
| Socket.io Client | Real-time WebSocket events |
Plain useState / useCallback |
No external state library needed at this scale |
| Node.js + Express | HTTP server |
TypeScript + tsx |
Runtime and type safety |
| Socket.io | WebSocket server |
| Sequelize v6 | ORM |
| Zod | Request validation |
| PostgreSQL (Neon) | Primary database |
| Vercel | Frontend deployment |
| Railway / Render | Backend deployment |
┌─────────────────┐
│ React Client │ ← Vite dev server (port 5173)
└────────┬────────┘
│ REST API (HTTP)
│ WebSocket (Socket.io)
▼
┌─────────────────┐
│ Express Server │ ← port 5000
└────────┬────────┘
│ Sequelize ORM
▼
┌─────────────────┐
│ PostgreSQL │ ← Neon (serverless Postgres)
└────────┬────────┘
│
▼
┌─────────────────────┐
│ Expiration Sweep Job │ ← runs every 5 seconds in-process
└────────┬────────────┘
│ emits socket events on expiry
▼
┌─────────────────────┐
│ Socket.io Broadcast │
└─────────────────────┘
| Column | Type |
|---|---|
| id | UUID (PK) |
| username | VARCHAR |
| createdAt | TIMESTAMP |
| Column | Type |
|---|---|
| id | UUID (PK) |
| name | VARCHAR |
| price | DECIMAL |
| totalStock | INTEGER |
| availableStock | INTEGER |
| startsAt | TIMESTAMP |
| createdAt | TIMESTAMP |
| Column | Type |
|---|---|
| id | UUID (PK) |
| userId | UUID (FK → Users) |
| dropId | UUID (FK → Drops) |
| status | ENUM: active, purchased, expired |
| expiresAt | TIMESTAMP |
| createdAt | TIMESTAMP |
| Column | Type |
|---|---|
| id | UUID (PK) |
| userId | UUID (FK → Users) |
| dropId | UUID (FK → Drops) |
| reservationId | UUID (FK → Reservations) |
| createdAt | TIMESTAMP |
User clicks Reserve
│
▼
status: ACTIVE
expiresAt: now + 60s
│
┌────┴────┐
│ │
▼ ▼
PURCHASED EXPIRED (sweep job fires)
│
▼
availableStock + 1
socket: stock:updated
Multiple users may attempt to reserve the last available item at the same millisecond.
availableStock = 1
100 users click Reserve simultaneously
→ Without concurrency control: overselling occurs
Stock decrement is executed as a single atomic SQL statement — no application-level lock needed:
UPDATE "Drops"
SET "availableStock" = "availableStock" - 1
WHERE id = :dropId
AND "availableStock" > 0;If the update affects 0 rows, the item is already claimed and the request receives a 409 Conflict immediately.
Running 100 concurrent reservation requests against a drop with availableStock = 1:
Run
npm run load-test
◇ injected env (0) from .env // tip: ⌘ custom filepath { path: '/custom/path/.env' }
Executing (default): SELECT 1+1 AS result
Executing (default): INSERT INTO "Drops" ("id","name","price","totalStock","availableStock","startsAt","createdAt","updatedAt") VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING "id","name","price","totalStock","availableStock","startsAt","createdAt","updatedAt";
Executing (default): INSERT INTO "Users" ("id","username","createdAt","updatedAt") VALUES ($1,$2,$3,$4) RETURNING "id","username","createdAt","updatedAt";
Firing 100 concurrent reserve requests at drop 2ba67c59-c076-4c62-afc1-ca44948e3a59 (stock = 1)...
Results: 1 succeeded (201), 99 rejected (409), 0 other
Executing (default): SELECT "id", "name", "price", "totalStock", "availableStock", "startsAt", "createdAt", "updatedAt" FROM "Drops" AS "Drop" WHERE "Drop"."id" = '2ba67c59-c076-4c62-afc1-ca44948e3a59';
Final availableStock in DB: 0
✅ PASS: exactly one reservation succeeded, stock correctly at 0
✓ 1 request → 201 Created (reservation granted)
✗ 99 requests → 409 Conflict (out of stock)
Zero oversells. The database constraint makes this guarantee hold regardless of server concurrency, connection pool size, or network timing.
A background sweep runs every 5 seconds inside the Express process:
- Query all
ACTIVEreservations whereexpiresAt < now - Mark them
EXPIREDin a single batch update - Increment
availableStockon the affected drops - Emit
stock:updatedvia Socket.io to all clients in the drop's room
This approach survives server restarts (state lives in Postgres, not memory) and requires no external scheduler.
| Event | Direction | Payload | Description |
|---|---|---|---|
joinDrop |
Client → Server | { dropId } |
Subscribe to a drop's room |
leaveDrop |
Client → Server | { dropId } |
Unsubscribe from a drop's room |
stock:updated |
Server → Client | { dropId } |
Stock count changed (reservation or expiry) |
purchase:completed |
Server → Client | { dropId, username, purchasedAt } |
A purchase was completed |
POST /api/users
Content-Type: application/json
{ "username": "alice" }Returns the user record (creates if username not yet registered).
GET /api/dropsResponse includes availableStock and recentPurchasers (last 3, newest first).
POST /api/drops
Content-Type: application/json
{
"name": "Air Jordan 1 Retro High OG",
"price": 250,
"totalStock": 10,
"startsAt": "2026-06-21T12:00:00Z"
}POST /api/drops/:dropId/reserve
Content-Type: application/json
{ "userId": "<uuid>" }Returns a Reservation with expiresAt 60 seconds from now. Returns 409 if out of stock.
POST /api/reservations/:reservationId/purchase
Content-Type: application/json
{ "userId": "<uuid>" }Returns 410 if the reservation has expired.
- Node.js ≥ 20
- A PostgreSQL database (Neon free tier works fine)
cd backend
npm installCreate backend/.env:
DATABASE_URL=postgresql://user:pass@host/dbname?sslmode=require
PORT=5000
NODE_ENV=developmentRun migrations, then seed demo data:
npx sequelize-cli db:migrate
npx sequelize-cli db:seed:all # optional — seeds 5 demo usersStart the dev server:
npm run devServer starts on http://localhost:5000.
cd frontend
npm installCreate frontend/.env:
VITE_API_URL=http://localhost:5000Start the dev server:
npm run devApp opens on http://localhost:5173.
With the backend running, create a drop via curl or Postman:
curl -X POST http://localhost:5000/api/drops \
-H "Content-Type: application/json" \
-d '{"name":"Air Jordan 1","price":250,"totalStock":5,"startsAt":"2026-01-01T00:00:00Z"}'Then open http://localhost:5173, enter a username, and the drop appears.
| Variable | Description |
|---|---|
DATABASE_URL |
Postgres connection string (Neon or local) |
PORT |
HTTP server port (default: 5000) |
NODE_ENV |
development or production |
| Variable | Description |
|---|---|
VITE_API_URL |
Backend base URL (e.g. http://localhost:5000) |
techzu.demo/
├── backend/
│ ├── src/
│ │ ├── config/ # Sequelize config, associations, env
│ │ ├── jobs/ # Expiration sweep job
│ │ ├── middlewares/ # Error handler, request validation
│ │ ├── migrations/ # Sequelize migrations (4 tables)
│ │ ├── modules/
│ │ │ ├── drops/ # Model, controller, routes, service, schema
│ │ │ ├── reservations/
│ │ │ ├── purchases/
│ │ │ └── users/
│ │ ├── scripts/ # Seed, load test, socket test client
│ │ ├── services/ # stock.service.ts (atomic decrement)
│ │ └── socket/ # Socket.io setup and event handlers
│ ├── .sequelizerc
│ └── package.json
│
└── frontend/
├── src/
│ ├── components/
│ │ ├── DropCard.tsx # Per-card state machine (idle→reserving→reserved→…)
│ │ ├── StockBadge.tsx # Colour-coded stock indicator
│ │ └── PurchaseFeed.tsx # Recent purchasers list
│ ├── hooks/
│ │ ├── useSocket.ts # Socket.io connection + room management
│ │ └── useCountdown.ts # 60s reservation countdown
│ ├── api.ts # Typed fetch wrappers + ApiError class
│ ├── types.ts # Shared TypeScript interfaces
│ └── App.tsx # Root: drops state, socket wiring, login screen
└── package.json
- Redis pub/sub for horizontal WebSocket scaling across multiple backend instances
- BullMQ for durable background job processing
- JWT authentication replacing the current username-based identity
- Rate limiting per user / IP
- Distributed locking (Redlock) for reservation critical sections
- Monitoring and observability (OpenTelemetry, Sentry)
- Admin dashboard for managing drops in real time
Sheikh Sakib Ahmed. Full Stack Developer
