Production Stack Benchmark — Validation Checks
validate.sh brings up the full production-stack compose (edge + cache + authsvc + server) with up --build -d, waits up to 60 seconds for the HTTPS port to respond, runs the checks below, and tears the stack down.
Checks performed
Protocol and static files
- HTTP/2 protocol negotiation -
curl --http2 /static/reset.cssmust report HTTP/2 /static/reset.css- Content-Typetext/css/static/app.js- non-zero response body
Public endpoints (no auth)
/public/baseline?a=13&b=42- returns55/public/baseline?a=<random>&b=<random>- correct sum (anti-cheat)/public/json/25- 25 items, each with the full schema (id,name,category,price,quantity,active,tags,ratingwithscore+count) and computedtotal = price × quantity
Auth wall - JWT required
GET /api/items/1(no Authorization header) - HTTP 401GET /api/items/1(Authorization: Bearer invalid.token.here) - HTTP 401POST /api/items/1(no Authorization header) - HTTP 401POST /api/items/1(Authorization: Bearer invalid.token.here) - HTTP 401
Authenticated CRUD - valid JWT
GET /api/items/1with valid JWT - returns item withid=1- Cache-aside cycle -
GET /api/items/7twice:- First call:
X-Cache: MISS(L1+L2 cold → Postgres query → populate both layers) - Second call:
X-Cache: HIT(served from L1 or L2)
- First call:
POST /api/items/2with valid JWT + JSON body - returns204 No Content(Postgres UPDATE + cache invalidation)- POST invalidation - warm cache for item 3, POST to item 3, GET item 3 again:
- GET after POST shows
X-Cache: MISS(provesRemoveAsynccleared both L1 and L2)
- GET after POST shows
GET /api/mewith valid JWT - returns user JSON withid=42(authsvc extractssub:42from the JWT, edge forwardsX-User-Id: 42, server reads user from Postgres via HybridCache)
Total: 15 production-stack checks plus the compose startup itself.
What validation proves
- JWT verification works end-to-end: valid tokens authenticate, invalid/missing tokens get 401
- Both GET and POST are behind the auth wall: can't read or write without a valid JWT
- Cache-aside populates on miss: first read of a cold key hits Postgres and populates cache
- Cache-aside serves from cache on hit: second read returns cached data
- POST invalidates cache: write clears both L1 and L2, forcing next read to re-query Postgres
- User lookup chain works: JWT
subclaim → authsvc → X-User-Id header → server → Postgres/cache → user JSON
JWT token for validation
Validation uses the pre-generated token at data/jwt-token.txt, signed with the secret httparena-bench-secret-do-not-use-in-production. The token contains {"sub":"42","name":"Alice Chen","exp":<far-future>}. authsvc verifies the HMAC-SHA256 signature and returns X-User-Id: 42.