GoShop in Node.js: 40 endpoints, idempotency and a degraded mode
NodeJs (the GoShop sample) is the
Node.js sibling of the Go
shopping service: an Express application with a 40-endpoint HTTP surface, PostgreSQL,
Redis caching, JWT auth with TOTP 2FA, and an email outbox worker. Stack: Node 20+, Express 4,
pg, ioredis, jsonwebtoken, otplib,
bcryptjs.
The route map
| Group | Routes |
|---|---|
| healthz | GET /healthz |
| customers + auth | 13 |
| products | 5 |
| cart | 6 |
| orders | 4 |
| payments | 6 |
| shipping | 5 |
Boot order in src/server.js reads like a checklist: connect the pool → run
embedded migrations → attach Redis (falling back to a no-op Null cache in degraded
mode when Redis is unreachable) → token manager → services → seed demo data → mount
the router → listen with graceful shutdown.
Three disciplines the sample hammers
- Idempotency everywhere. A single shared
IdempotencyGuardwraps the risky verbs, so network retries cannot double-charge or double-create. - Retry with backoff. Transient failures between services get exponential backoff — the same idea as the ResilientSqlAccess library, in JavaScript.
- Tests with no infrastructure. All 20 tests run in-memory: an in-memory
pgseam plus real Express mounts meansnpm testneeds no database and no Redis, yet still exercises full HTTP routes.
What the email outbox teaches
Instead of sending email inline (slow, and what if SMTP is down?), requests append to an
outbox table and src/email/worker.js drains it separately. Your checkout stays
fast, and email becomes retryable work instead of a failure mode.
Repository: github.com/bobhuang1/NodeJs — the per-endpoint breakdown lives in ROUTES.md.