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)

  1. Skim before labs or interviews.
  2. Drill gaps — reopen README.md6.8.a6.8.c.
  3. Practice6.8-Exercise-Questions.md.
  4. Polish answers6.8-Interview-Questions.md.

Core Vocabulary

TermOne-liner
Rate limitingRestricting how many requests a client can make per time window
Token bucketRate limiting algorithm that allows controlled bursts; tokens refill steadily
Leaky bucketRate limiting algorithm that enforces perfectly smooth output rate
Sliding windowRate limiting that avoids burst-at-boundary by weighting across windows
429 Too Many RequestsHTTP status code returned when a rate limit is exceeded
CORSCross-Origin Resource Sharing — server opt-in to allow cross-origin browser requests
Same-Origin PolicyBrowser security rule: JS on one origin cannot read responses from another
Preflight (OPTIONS)Browser check before non-simple cross-origin requests
CSPContent-Security-Policy — controls which resources the browser can load
HSTSHTTP Strict Transport Security — forces HTTPS connections
Helmet.jsExpress middleware that sets all standard security headers in one call
DDoSDistributed Denial of Service — overwhelming a system from many sources
WAFWeb Application Firewall — inspects HTTP requests and blocks malicious patterns
AWS ShieldAWS service that protects against L3/L4 DDoS attacks (Standard = free)
SlowlorisAttack that holds connections open with slow header transmission
Geo-blockingRestricting 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

HeaderValuePrevents
Content-Security-Policydefault-src 'self'XSS, code injection
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preloadHTTP downgrade
X-Content-Type-OptionsnosniffMIME sniffing
X-Frame-OptionsDENYClickjacking
X-XSS-Protection0Legacy XSS filter issues
Referrer-Policystrict-origin-when-cross-originReferrer leakage
Cross-Origin-Opener-Policysame-originCross-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

GotchaWhy
In-memory rate limiting breaks with multiple serversCounters not shared — use Redis
cors({ origin: '*' }) in productionAny website can call your API
Reflecting Origin header without validationSame as wildcard — allows any origin
Missing exposedHeaders in CORSFrontend JS cannot read custom response headers
headersTimeout too high (default 60s)Slowloris can hold connections for up to 60 seconds
No rate limit on /loginEnables brute-force attacks
HSTS with broken certUsers locked out — cannot bypass cert error
Shield Advanced without CloudFrontMisses the biggest protection layer
WAF only — no app-level limitsL7 floods with valid requests pass WAF
Hardcoded CORS originsBreaks 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.