Ahmed Abdelaziz

Custom Ecommerce Backend API for a Clothing BrandDesign Docs

Architecture

Fullstack system — API monolith on Render/Neon, storefront proxy on Vercel, auth flow, concurrency and reporting pipeline.

Last updated September 2026

Overview

A complete clothing-store platform in two apps: a TypeScript/Express REST API owning all business rules and data, and a Next.js application that is both the customer storefront and the admin console. One PostgreSQL database, zero client-side business logic.

The clever part

The storefront rewrites /api/v1/* to the backend at the edge. The browser only ever talks to one origin — so session cookies stay first-party (SameSite=Lax) and CORS simply doesn't exist in this system.


Backend: A Disciplined Monolith

Sixteen domain modules (auth, users, addresses, products, categories, cart, orders, reviews, inventory, coupons, uploads, admins, analytics, reports, audit, stats), each with the same five layers:

routes → controller → service → repository → Prisma
  • Routes declare method + path + zod schema + required roles.
  • Services hold business rules and transactions — no HTTP concepts.
  • Repositories own every Prisma query and soft-delete filter.
  • Plain function composition throughout — no classes, no DI framework.

Cross-cutting concerns are middleware: trust proxy for correct IP behind Render/Neon, helmet, CORS (single CORS_ORIGIN — drives both CORS and email links), cookie parsing, pino request logging with x-request-id correlation and sensitive-field redaction, global + endpoint-specific rate limiters (TRUST_PROXY-aware; global limiter skipped in test), double-submit CSRF bound to the session (csrf-csrf, fails closed in production, ENABLE_CSRF boot guard), audit logging of every authenticated /admin/* mutation, health probes (/health, /health/ready with 2s DB timeout) outside the limiter, and a central error handler that maps Prisma P2002/P2025/22001 to typed HTTP failures.


Authentication Flow

Opaque server-side sessions — never JWTs:

Roles: CUSTOMER, ADMIN, SUPER_ADMIN. Admin routers require ADMIN; role changes, admin management, audit logs, and analytics require SUPER_ADMIN.


Concurrency: Where This Backend Earns Its Keep

Commerce correctness under simultaneous requests:

  • Checkout runs inside one transaction guarded by a per-user pg_advisory_xact_lock — coupon redemption, stock reservation, snapshots, payment, and cart clear share one rollback boundary.
  • Stock reservation uses a guarded conditional UPDATE (available >= qty) — overselling is structurally impossible; cancellation before fulfillment restores coupon quota atomically, post-fulfillment refunds keep it consumed.
  • Order status transitions follow an explicit allowedTransitions FSM executed under SELECT ... FOR UPDATE, with side effects (shipment creation, stock commit/release, payment status, coupon quota) asserted by affected-row counts.
  • Cart mutations are also advisory-locked — add, update, remove, and clear all route through the same withUserCartLock so concurrent cart vs checkout requests degrade to documented 404s, never 500s.
  • Every race has a named regression test: registerRace, productSlugRace, categoryAssignRace, cart.race / cartConcurrency (checkout vs clear/update, duplicate deletes), last-admin protection.

Why it matters

Most portfolio backends demonstrate happy paths. This one demonstrates what happens when two people click "Buy" at the same time.


The Client: Storefront Plus Admin Console

The Next.js app is feature-sliced (features/<domain>/api.ts + hooks.ts + components/), with TanStack Query for all server state (centralized query-key factory), React Hook Form + zod on 17 forms, and a heavily engineered Axios layer: envelope unwrapping (two pagination dialects), typed error normalization, CSRF token deduplication with retry-once recovery, and session-expiry eventing.

It includes a full role-gated admin console — catalog with variant/image editors, inventory adjustments, order status transitions, review moderation, user/role management, coupons, and analytics dashboards.


Honest Gaps

  • Payments are mocked — a pluggable PaymentGateway interface exists; real integration (Paymob tasks T-081–T-087) is tracked.
  • Reports are SUPER_ADMIN-only PDFs — pdfkit vector tables + line/bar/pie charts with Intl.NumberFormat currency (USD|EUR|GBP|EGP|SAR|AED), streaming application/pdf (Cache-Control: no-store, Content-Disposition: attachment|inline, X-Report-Currency) and ?format=json preview; pure pdfkit, no native canvas/Chromium.
  • SMS is a stub that logs instead of sending (tracked T-009).
  • Review purchase-verification is flag-gated off (REVIEWS_REQUIRE_PURCHASE = false).
  • Rate limiting is per-instance in memory — effective limits multiply behind N instances; mitigation is single instance or a shared Redis store (documented in docs/DEPLOYMENT.md §2).
  • Admin visibility on the client works by probing endpoints (200 vs 403) — explicitly documented as UI-only convenience; the API enforces real authorization.
  • OpenAPI 3.1 spec (77 paths) exists but markdown contracts in docs/api/** remain authoritative, and CI linting of the spec is pending (T-011/T-054).

Result

A fullstack commerce platform where every hard problem — stock races, idempotent order history, session security, image provenance — has an explicit, tested answer.