Episode 6 — Scaling Reliability Microservices Web3 / 6.8 — Production Hardening
6.8 — Production Hardening: Quick Revision
Compact cheat sheet. Print-friendly.
How to use this material (instructions)
- Skim before labs or interviews.
- Drill gaps — reopen
README.md→6.8.a…6.8.c. - Practice —
6.8-Exercise-Questions.md. - Polish answers —
6.8-Interview-Questions.md.
Core Vocabulary
| Term | One-liner |
|---|---|
| Rate limiting | Restricting how many requests a client can make per time window |
| Token bucket | Rate limiting algorithm that allows controlled bursts; tokens refill steadily |
| Leaky bucket | Rate limiting algorithm that enforces perfectly smooth output rate |
| Sliding window | Rate limiting that avoids burst-at-boundary by weighting across windows |
| 429 Too Many Requests | HTTP status code returned when a rate limit is exceeded |
| CORS | Cross-Origin Resource Sharing — server opt-in to allow cross-origin browser requests |
| Same-Origin Policy | Browser security rule: JS on one origin cannot read responses from another |
| Preflight (OPTIONS) | Browser check before non-simple cross-origin requests |
| CSP | Content-Security-Policy — controls which resources the browser can load |
| HSTS | HTTP Strict Transport Security — forces HTTPS connections |
| Helmet.js | Express middleware that sets all standard security headers in one call |
| DDoS | Distributed Denial of Service — overwhelming a system from many sources |
| WAF | Web Application Firewall — inspects HTTP requests and blocks malicious patterns |
| AWS Shield | AWS service that protects against L3/L4 DDoS attacks (Standard = free) |
| Slowloris | Attack that holds connections open with slow header transmission |
| Geo-blocking | Restricting access by geographic location (country) |
Rate Limiting Algorithms Comparison
┌─────────────────────┬───────────┬────────┬───────────┬────────────────────┐
│ Algorithm │ Burst │ Memory │ Precision │ Best For │
├─────────────────────┼───────────┼────────┼───────────┼────────────────────┤
│ Fixed Window │ Poor │ Low │ Low │ Basic / low-risk │
│ Sliding Window Log │ Excellent │ High │ Exact │ Low-volume precise │
│ Sliding Window Ctr │ Good │ Low │ Near-exact│ Most production │
│ Token Bucket │ Controlled│ Medium │ Good │ APIs with bursts │
│ Leaky Bucket │ None │ Medium │ Good │ Smooth output │
└─────────────────────┴───────────┴────────┴───────────┴────────────────────┘
Rate Limiting Quick Setup
// Minimum viable rate limiting (Express)
import rateLimit from 'express-rate-limit';
app.use(rateLimit({
windowMs: 15 * 60 * 1000, // 15 min
max: 100, // 100 requests
standardHeaders: true,
}));
// Auth endpoint (strict)
app.post('/api/auth/login', rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true,
}));
Rate Limit Headers
Response (200): Response (429):
RateLimit-Limit: 100 RateLimit-Limit: 100
RateLimit-Remaining: 42 RateLimit-Remaining: 0
RateLimit-Reset: 1625847600 RateLimit-Reset: 1625847600
Retry-After: 30
CORS Checklist
[x] Whitelist specific origins (NEVER use * in production)
[x] Handle preflight (OPTIONS) — cors middleware does this
[x] Set credentials: true if using cookies
[x] Expose custom headers (RateLimit-*, X-Request-Id)
[x] Cache preflight with maxAge (86400 = 24h)
[x] Use environment variables for origin list
[x] Log blocked origins for debugging
[x] Never reflect Origin header without validation
CORS Quick Setup
import cors from 'cors';
app.use(cors({
origin: ['https://app.example.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['RateLimit-Limit', 'RateLimit-Remaining'],
maxAge: 86400,
}));
CORS Rules with Credentials
credentials: true → origin CANNOT be *
→ allowedHeaders CANNOT be *
→ methods CANNOT be *
→ Must list specific values
Security Headers List
| Header | Value | Prevents |
|---|---|---|
Content-Security-Policy | default-src 'self' | XSS, code injection |
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | HTTP downgrade |
X-Content-Type-Options | nosniff | MIME sniffing |
X-Frame-Options | DENY | Clickjacking |
X-XSS-Protection | 0 | Legacy XSS filter issues |
Referrer-Policy | strict-origin-when-cross-origin | Referrer leakage |
Cross-Origin-Opener-Policy | same-origin | Cross-window attacks |
Security Headers Quick Setup
import helmet from 'helmet';
app.use(helmet()); // All defaults — good starting point
app.disable('x-powered-by'); // Remove Express fingerprint
Cookie Security
cookie: {
httpOnly: true, // No JS access (XSS protection)
secure: true, // HTTPS only
sameSite: 'strict', // No cross-site sending (CSRF protection)
maxAge: 86400000, // 24 hours
}
SameSite values:
Strict → Never sent cross-site (safest, may break OAuth redirects)
Lax → Sent on top-level navigation only (good default)
None → Always sent (requires Secure; needed for cross-site auth)
DDoS Protection Layers
Layer │ What │ Stops
─────────┼─────────────────────────┼────────────────────────────
Edge │ CloudFront/CloudFlare │ Volumetric (Tbps floods)
Shield │ AWS Shield Standard │ L3/L4 (SYN flood, UDP)
WAF │ AWS WAF rules │ L7 patterns (SQLi, XSS, bots)
Gateway │ Rate limiter (Redis) │ Per-user/IP abuse
App │ Timeouts, limits, queues│ Slowloris, payload bombs
DDoS Attack Types
Volumetric (L3/4): Flood bandwidth → CDN absorbs
Protocol (L3/4): Exhaust connections → Shield mitigates
Application (L7): Legitimate-looking → WAF + rate limit + app hardening
Server Timeout Settings (Anti-Slowloris)
const server = app.listen(3000);
server.headersTimeout = 20000; // 20s to send headers
server.requestTimeout = 30000; // 30s to complete request
server.keepAliveTimeout = 5000; // 5s idle keep-alive
server.timeout = 60000; // 60s total
Request Size Limits
app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ limit: '1mb', extended: true }));
AWS Shield Comparison
Feature │ Standard (Free) │ Advanced ($3K/month)
─────────────────────┼──────────────────────┼────────────────────────
L3/L4 protection │ Yes (automatic) │ Yes (enhanced)
DDoS Response Team │ No │ Yes (24/7)
Cost protection │ No │ Yes (credits for scaling)
Advanced detection │ Basic │ Traffic-pattern tailored
WAF integration │ No │ Auto-creates WAF rules
Health-based detect │ No │ Yes (Route 53 checks)
Common Gotchas
| Gotcha | Why |
|---|---|
| In-memory rate limiting breaks with multiple servers | Counters not shared — use Redis |
cors({ origin: '*' }) in production | Any website can call your API |
Reflecting Origin header without validation | Same as wildcard — allows any origin |
Missing exposedHeaders in CORS | Frontend JS cannot read custom response headers |
headersTimeout too high (default 60s) | Slowloris can hold connections for up to 60 seconds |
No rate limit on /login | Enables brute-force attacks |
| HSTS with broken cert | Users locked out — cannot bypass cert error |
| Shield Advanced without CloudFront | Misses the biggest protection layer |
| WAF only — no app-level limits | L7 floods with valid requests pass WAF |
| Hardcoded CORS origins | Breaks when adding new frontends — use env vars |
Complete Hardening Middleware Stack
// Production Express middleware order
app.set('trust proxy', 1);
app.use(enforceHttps); // Redirect HTTP → HTTPS
app.use(helmet(helmetConfig)); // Secure headers
app.use(cors(corsConfig)); // CORS whitelist
app.use(express.json({ limit: '1mb' })); // Body size limit
app.use(globalRateLimiter); // 500 req/15min (Redis)
app.post('/auth/*', authLimiter); // 5 attempts/15min
app.use(requestTimeout(30000)); // 30s timeout
End of 6.8 quick revision.