Edge and NGINX Delivery Architecture
Why this chapter matters
Frontend architecture does not stop at the framework boundary. The reverse proxy, CDN, load balancer, compression settings, cache keys, TLS policy, health checks, logs, and static asset rules shape the user's experience before application code runs.
The NGINX and browser networking source material makes one pattern clear: delivery infrastructure is product infrastructure. A misconfigured redirect, cache purge, compression rule, proxy timeout, or health check can become a frontend outage. A well-designed edge layer can reduce latency, absorb traffic spikes, improve reliability, and make incidents easier to diagnose.
Core mental model
The edge is a programmable delivery contract.
It decides:
- how users reach the application
- which requests are served without origin work
- which failures are retried, hidden, degraded, or exposed
- which assets are compressed, cached, and prioritized
- which logs and metrics let teams explain real user symptoms
Architects should treat edge behavior as part of the frontend system design, not an operations detail owned somewhere else.
Source-derived architecture notes
- Reverse proxies and CDNs can improve latency only when cache keys, static asset immutability, compression, redirects, and origin shielding are designed intentionally.
- Load balancing is not only distribution; it encodes health, stickiness, failover, draining, canaries, and blast-radius control.
- Brotli and gzip reduce transfer size but do not reduce JavaScript parse or execution cost. Compression is a delivery optimization, not a license to ship unlimited code.
- Cache purging is dangerous when it is unauthenticated, global by default, or not observable. Purge architecture needs authorization, scope, logs, and rollback behavior.
- Access and error logs are architecture assets. They connect browser symptoms to edge behavior, origin latency, cache hits, retries, and release changes.
Architecture decision framework
| Decision | Conservative option | Flexible option | Tradeoff signal |
|---|---|---|---|
| Static assets | Immutable hashed filenames | Mutable URLs with short TTL | Use immutable assets when build pipeline controls filenames. |
| HTML caching | Short TTL or revalidation | Longer edge cache | Extend only when personalization and freshness are clearly bounded. |
| Compression | Brotli/gzip for text assets | No compression or origin-only | Compress at edge when CPU cost and cache behavior are understood. |
| Load balancing | Health-aware draining | Simple round-robin | Add health and drain behavior when deploys or origin failure affect users. |
| Purge policy | Scoped authenticated purge | Broad manual purge | Scope purge by surrogate key, route, tenant, or release where possible. |
Implementation patterns
Baseline pattern for small teams
Define the delivery contract for the top routes:
- redirect and canonical URL rules
- TLS and secure header expectations
- static asset TTL and immutable filename policy
- HTML caching and revalidation policy
- compression behavior for HTML, CSS, JS, JSON, SVG, and fonts
- proxy timeout and retry behavior
- access log fields needed for debugging
For most frontend apps, the first high-value move is simple: immutable static assets, conservative HTML caching, Brotli/gzip enabled for text, route-level cache headers, and logs that include request id, cache status, upstream time, status, route, and release where possible.
Scale pattern for multi-team organizations
At scale, the edge needs governance:
- route ownership for cache and timeout policy
- safe defaults for all frontend apps
- canary and blue/green rules that support rollback
- health checks that distinguish app readiness from process liveness
- shared observability dimensions for tenant, region, release, status, cache state, and upstream
- documented purge workflow with approval, audit trail, and blast-radius notes
The goal is not to make every team learn NGINX deeply. The goal is to turn repeated delivery decisions into reusable platform contracts.
Migration-safe pattern for legacy systems
Start by observing before changing:
- Map the current request path from browser to CDN, proxy, origin, and backend.
- Capture cache headers, compression, redirects, status codes, and upstream timings for top routes.
- Fix static asset caching first because hashed assets are usually low-risk.
- Introduce scoped cache purge and release correlation before increasing HTML TTLs.
- Move risky changes through canary or percentage rollout.
Anti-patterns and failure modes
- Symptom: a deploy breaks only some users. Root cause: cached HTML references missing or purged assets. Prevention control: immutable assets and deploy ordering that keeps old assets available.
- Symptom: origin traffic spikes after a release. Root cause: cache key or header change bypasses edge caching. Prevention control: cache hit alerts and release-correlated edge dashboards.
- Symptom: users see stale personalized content. Root cause: shared cache does not vary on auth, tenant, locale, or personalization boundary. Prevention control: explicit cache key design and private/no-store rules where needed.
- Symptom: incident diagnosis stalls. Root cause: edge logs lack upstream time, cache status, release, or request correlation. Prevention control: structured access logs and trace propagation.
- Symptom: purge fixes one issue but causes another. Root cause: global purge is used as a blunt instrument. Prevention control: scoped purge and documented rollback.
Verification checklist
- Static assets use immutable URLs and long cache lifetimes.
- HTML, API, and asset cache policies are documented separately.
- Compression is enabled and verified for eligible text formats.
- Proxy timeouts, retries, and upstream failure behavior are explicit.
- Health checks represent user-serving readiness, not only process existence.
- Access logs include cache status, upstream time, status, request id, route, and release signal.
- Cache purge is authenticated, scoped, logged, and reversible where possible.
Metrics and scorecards
Track leading indicators:
- edge cache hit ratio by route and asset type
- origin request rate
- p95/p99 upstream response time
- 4xx/5xx rate by route and region
- compression coverage and transfer savings
- purge count and purge blast radius
Track lagging indicators:
- delivery incidents caused by cache, redirects, or proxy behavior
- user-facing stale content reports
- rollback time for edge-related releases
Deep architecture model
Request path as an owned system
For every critical route, draw the delivery path as a chain:
browser -> DNS -> CDN/edge -> reverse proxy -> origin app -> BFF/API -> data service
Each hop needs an owner and a failure policy. The common architectural mistake is optimizing only the application server while leaving redirects, compression, cache misses, proxy buffering, timeout behavior, and logs as undocumented defaults.
| Hop | Design questions | Failure signal |
|---|---|---|
| DNS and CDN | Are users routed to the nearest healthy edge? Are redirects minimized? | high connect time, regional failures |
| Edge cache | What is cacheable, private, stale, or revalidated? | hit-ratio drop, stale reports |
| Reverse proxy | What are timeouts, body limits, buffering, and retry rules? | 502/504 spikes, upstream wait |
| Origin app | Is rendering CPU-bound, I/O-bound, or cache-bound? | high TTFB, queueing |
| APIs | Are payloads route-shaped and cache-aware? | waterfalls, duplicate requests |
| Logs/traces | Can a user report be correlated across layers? | incident diagnosis stalls |
Cache policy matrix
Do not use one cache policy for the whole frontend. Use a matrix:
| Resource | Recommended policy | Notes |
|---|---|---|
| Hashed JS/CSS | long TTL, immutable | keep old assets available across deploys |
| HTML shell | short TTL, revalidate, or stale-while-revalidate | depends on personalization and deploy model |
| Public images | long TTL with transform/version key | include dimensions and format negotiation |
| Fonts | long TTL, immutable where possible | watch CORS and preload correctness |
| API JSON public | explicit TTL and surrogate key | document stale tolerance |
| API JSON private | private/no-store or user-specific cache | do not share across auth/tenant boundaries |
| Error pages | short TTL or no-store | avoid caching transient failure as truth |
The frontend architect should make cache behavior visible in code review. A feature that changes personalization, tenant scoping, locale, auth, or experiment exposure can invalidate an old cache assumption.
Safe deploy ordering
Many frontend delivery incidents come from asset/HTML mismatch. A safer release sequence is:
- Upload new immutable assets.
- Verify assets are reachable from the edge.
- Deploy server or HTML that references new assets.
- Keep previous assets available for at least the maximum HTML cache lifetime.
- Purge or revalidate HTML only after the new path is verified.
- Monitor 404s for assets, HTML error rate, and route-level client errors.
If an organization cannot keep old assets, HTML caching must be much more conservative. The cache and deploy strategies are coupled.
Compression and transfer policy
Compression should be deliberate:
| Asset | Compression guidance | Architectural caveat |
|---|---|---|
| HTML/CSS/JS/JSON/SVG | Brotli/gzip where supported | transfer savings do not remove parse/execute cost |
| Fonts | usually already compressed formats | verify CORS and cache headers |
| JPEG/PNG/WebP/AVIF | image encoding, not gzip | use format negotiation and dimensions |
| Streaming data | depends on chunking and latency | compression may add buffering or CPU cost |
Brotli often improves static text asset transfer, but it should be paired with bundle budgets. Shipping 1 MB less compressed is still worse than not shipping unnecessary JavaScript.
Health checks, load balancing, and draining
A frontend-serving origin should expose readiness in user-serving terms. "Process is alive" is not enough. Readiness may need to account for template rendering, dependency availability, cache warmup, configuration, and ability to serve critical routes.
Load balancing policy should define:
- how unhealthy origins are removed
- how long in-flight requests drain during deploy
- whether sessions are sticky and why
- whether retries are safe for idempotent requests only
- how canary traffic is selected and observed
- how rollback affects cached HTML and assets
Retries at the proxy can hide transient failure, but they can also duplicate unsafe requests or amplify load. Document retry methods and status codes explicitly.
Operational runbooks
Cache purge runbook
Before purge:
- identify resource class: HTML, API, asset, image transform, tenant, locale, experiment
- confirm owner and reason
- choose scope: surrogate key, route, prefix, tenant, full zone
- estimate blast radius and origin load impact
- verify rollback or rewarm path
After purge:
- watch cache hit ratio, origin traffic, p95 TTFB, 5xx rate, and user errors
- record who purged, why, scope, and observed outcome
- add a follow-up if purge was used to compensate for missing invalidation design
Edge incident triage
Ask in order:
- Did the request reach the edge?
- Was it cache hit, miss, stale, bypass, or error?
- Did the edge contact origin?
- What was upstream time and status?
- Did a recent deploy change cache headers, redirects, asset names, or proxy config?
- Is the problem regional, route-specific, tenant-specific, or global?
- Are client errors caused by missing assets or bad HTML references?
Exercises
- Draw the full delivery path for one route from browser to origin. Mark every cache and timeout boundary.
- Write a cache policy for HTML, JavaScript, CSS, fonts, images, and API JSON.
- Design an edge dashboard for a frontend incident: what panels prove cache, origin, and client behavior?
- Write a purge runbook that includes authorization, scope, expected evidence, and rollback.
Source Lens
This chapter is synthesized from:
- Mastering NGINX for Site Reliability - reverse proxy architecture, load balancing, health checks, compression, caching, purging, logs, and limits.
- High Performance Browser Networking - HTTP/TLS delivery behavior, cache and protocol tradeoffs, and browser networking constraints.
- High Performance Browser Networking Special Edition NGINX - HTTP/2 delivery guidance and evergreen performance practices.