Selected project01

ShopNest

A commerce system engineered for correctness under concurrency — atomic inventory, idempotent checkout, refresh-token theft detection, and order history that survives catalogue changes.

Scope

Product thinking, engineering decisions, system structure, and implementation.

ShopNest
ShopNest commerce interface showing product discovery, product details, cart state, pricing, and checkout controls.
01

Role

Backend architecture, data modelling, and full-stack implementation

02

Timeline

2025—26

03

Core stack

NestJS 11 · Next.js 15 · TypeScript · Prisma

01

The problem

What made this worth solving?

A storefront is easy until two customers try to buy the final unit at the same moment. Commerce correctness lives in races around inventory, duplicate checkout requests, authentication sessions, and preserving historical order data after products change.

02

Engineering approach

How the system was shaped.

The project uses a Turborepo monorepo with a NestJS API and Next.js frontend sharing OpenAPI-generated TypeScript contracts. Money is represented as integer cents rather than floating point. Order items snapshot purchase-time data so later catalogue changes cannot rewrite history, while checkout correctness is enforced inside database transactions rather than through application-level reads.

Technology08 tools
  • 01NestJS 11
  • 02Next.js 15
  • 03TypeScript
  • 04Prisma
  • 05PostgreSQL 17
  • 06Turborepo
  • 07Argon2id
  • 08GitHub Actions
03

Hardest technical problem

The part that needed real engineering.

AFailure mode

Two concurrent checkouts can both observe the final unit as available before either decrements it. Row locking fixes that race, but locking overlapping carts in inconsistent order introduces deadlocks.

BResolution

The cart acts as the serialization point, product rows are acquired in deterministic order, and stock is decremented with a conditional update only when enough quantity remains. A zero-row update means another transaction won, so the request fails safely instead of allowing negative inventory.

04

Outcome

What the work produced.

Concurrency-sensitive behaviour is covered by automated tests, and important architectural decisions are documented explicitly instead of being left implicit in implementation details.

05

Looking back

What I would change today.

One authentication path originally revoked a compromised token family and then threw inside the same transaction, causing the revocation to roll back. The fix reinforced an important boundary: transactions should return a decision; control flow should happen after the transaction commits.

Design the behaviour. Engineer for what happens next.

Continue exploring

Next case study

NEXT / 01
Tech Blog