STDNT GEAR
B2B commerce platform where institutions self-serve branded apparel quotes — built solo, end to end.
- Role
- Founding Engineer (solo)
- Timeframe
- Apr 2024 — Present

At a glance
Institutions ordering custom apparel used to quote by email. STDNT GEAR lets buyers browse a real catalogue, configure designs, and generate priced quotes themselves — while staff keep final approval.
- Solo-built, production-ready platform
- Self-service quote wizard replaces email loops
- 3,000+ products synced from vendor API
- Server-locked pricing — quotes can’t be tampered client-side
Clients
API
Data
One API serves both frontends. A scheduled job keeps the catalogue in sync with the vendor.
What shipped
Four connected surfaces — discovery, catalogue, quoting, and account tracking.
Storefront
Category-led discovery
Catalogue
Faceted search at scale
Quote builder
3-step wizard
Portal
PDF quotes + tracking
Storefront
The public site is the primary sales surface — not a landing page bolted onto admin.
Catalogue & discovery
Cached category trees and parallel facet queries keep 3,000+ products fast to filter.

Quote builder
Three-step wizard with server-calculated totals at every step.
Step 1 — per-size quantities against live stock.
Submission & portal
Branded PDF quotes, reference numbers, and self-service status tracking.
For engineers
Technical deep dive
Problem context, engineering decisions, security hardening, and honest scope boundaries.
For engineers
Technical deep dive
Problem context, engineering decisions, security hardening, and honest scope boundaries.
The problem
Schools, sports clubs, and corporate teams ordering branded apparel typically quote by email — slow, opaque, and hard to scale. STDNT GEAR replaces that with self-service quoting while staff retain manual approval before invoicing.
Role & scope
Solo engineer — every layer from schema to deployment:
- PostgreSQL schema (27 tables) and Express REST API (~70 endpoints).
- Customer storefront and staff admin portal (both React).
- Vendor catalogue ingestion pipeline (3,000+ products, prices, stock, swatches).
- Production deployment and operations.
Key engineering decisions
Vendor catalogue ingestion pipeline
The vendor API returns thousands of products with nested variants, prices, stock, and colour swatches. Naively inserting everything concurrently caused PostgreSQL deadlocks under load, and a single failed record could kill the whole sync.
- Single-threaded sequential inserts — safe but far too slow for a full catalogue refresh.
- High concurrency (10+ parallel batches) — fast, but frequent deadlocks on shared indexes.
- Smart batching with capped concurrency and per-operation retry.
Grouped products into batches of 50 (partitioned to reduce key overlap), capped concurrency at 2 in-flight batches, and wrapped every write in deadlock-aware retry with exponential backoff.
A full catalogue sync is slower than it could theoretically be, but it runs unattended and self-heals from transient PostgreSQL deadlocks instead of failing the whole job.
Server-authoritative pricing
Quotes and invoices involve price adjustments (staff discounts, corrections). If a client ever computed or held the authoritative total, a tampered request could change what a customer owes.
- Trust the price the client submits with the quote.
- Recompute and lock the total server-side whenever a quote is priced or converted to an invoice.
Every quote total is calculated and locked server-side. Staff-applied adjustments are stored as discrete line items, not baked into a single mutable total, so invoice history stays auditable.
More server-side computation and stricter API contracts, in exchange for pricing integrity that can't be bypassed from the client.
Caching strategy for the product catalogue
Category trees and multi-facet product filters (brand, gender, material, fit, price) get slow at scale if every filter click hits PostgreSQL with fresh joins.
- No caching — simplest, but filter interactions get sluggish as the catalogue grows.
- Cache everything in Redis from day one.
- Layer caches by volatility: in-memory for near-static data, React Query for per-user UI state, Redis reserved for cross-instance needs.
Cache the category hierarchy in server memory with TTL + explicit invalidation on writes, run facet-count queries in parallel rather than sequentially, and let React Query handle client-side staleness.
In-memory cache doesn't survive a restart or share state across multiple server instances — acceptable for current scale, with Redis already integrated as the upgrade path.
Security & auth
JWT with short-lived access tokens and HttpOnly refresh tokens, plus optional Google OAuth. Account lockout after repeated failed logins, audit logging of auth events, and rate limiting on auth endpoints.
Hardest problems
Keeping a large, frequently-changing external catalogue consistent with an internal schema that also supports fast filtering. Deadlocks under concurrent writes, cache invalidation after syncs, and a quote data model flexible enough for arbitrary print positions without becoming an unstructured blob.