Designing a High-Performance Static+Dynamic Web Architecture with CDN and Next.js

June 18, 2025

Building a performant, scalable web application today often means combining static assets, dynamic APIs, and real-time communication through a CDN edge. In this post, we explore four axes of modern architecture:

  1. CDN + Backend vs. CDN + Middleware + Backend (and an alternative client-side-rendered frontend)
  2. Next.js: Full Static Generation vs. Incremental Rendering
  3. CI/CD: PR-Driven vs. Data-Driven Pipelines
  4. CloudFront Configuration Highlights

1. CDN + Backend vs. CDN + Middleware + Backend

```mermaid flowchart LR subgraph Edge A[Client] -->|HTTPS| B[CloudFront CDN] end subgraph Origin B --> C[Middleware Layer] C --> D[Backend API] end subgraph Direct B --> E[Backend API] end ```
PatternLatency (ms)Throughput (rps)Complexity
CDN β†’ Backend~𝑂(𝑑ₙ)𝑅_maxLow
CDN β†’ Middleware β†’ Backend~𝑂(𝑑ₙ + π‘‘β‚˜)𝑅_max Γ— 0.8Medium
CDN + CSR Frontend~𝑂(𝑑ₙ + 𝑑𝑐)𝑅_max Γ— 0.9Low (no SSR)
  • 𝑑ₙ: edge-to-origin network delay
  • π‘‘β‚˜: middleware processing
  • 𝑑𝑐: client-side render time
  • 𝑅_max: CDN origin throughput
Communication StyleBest Fit
Real-time (WebSocket)CDN β†’ Middleware β†’ Backend (edge Lambda@Edge keeps WS alive)
Event-DrivenCDN β†’ Backend (API Gateway + SNS/SQS)
Data-DrivenCDN β†’ Middleware β†’ Backend (GraphQL orchestration)

Key takeaway:

  • Direct CDN β†’ Backend delivers lowest complexity and latency for pure API calls.
  • Middleware allows edge logic (A/B tests, auth) but adds ~π‘‘β‚˜ ms.
  • CSR frontend offloads SSR entirely but shifts work to the client (𝑑𝑐).

2. Next.js: Static Generation vs. Incremental Rendering

Next.js supports three primary rendering modes:

ModeBuild-time CostPer-request CostFreshnessUse Case
SSG𝑂(𝑁) pages𝑂(1)Stale until rebuildMarketing, docs
ISR𝑂(1) initial build𝑂(1) + revalidateTTL-based freshnessBlogs, catalogs
SSR𝑂(1)𝑂(1)Always liveAuthenticated dashboards

If you statically export 𝑁 = 1000 pages at build time, cost ∼1000 Γ— 𝑑_render. With ISR, cost reduces to one‐time 𝑑_render + soft rebuilds on-demand.

sequenceDiagram participant B as Build participant U as User participant S as Server B->>FS: render all pages (𝑂(𝑁)) U->>CDN: request page CDN->>S: if stale (ISR) or dynamic (SSR) S->>CDN: render + cache CDN->>U: serve page

3. CI/CD: PR-Driven vs. Data-Driven Pipelines

TriggerProsCons
PR-DrivenFast feedback on code, lint, unit testsWastes runs on trivial changes
Data-DrivenTrigger on metrics (e.g. 𝑑_response > 200 ms)Complex to implement

Example:

  • PR Pipeline:

    • On pull request ⟢ run lint, unit tests, build
    • Cost: C_pr = π‘ž_pr Γ— 𝑐_job
  • Data-Driven Pipeline:

    • On production metric breach (error rate > 0.5%) ⟢ run smoke tests, rollback
    • Cost: C_dd = π‘ž_dd Γ— 𝑐_job, but π‘ž_dd β‰ͺ π‘ž_pr

Rule of thumb:

  • Use PR-driven for code correctness.
  • Use Data-driven for performance/regression monitoring and automated rollbacks.

4. CloudFront Configuration Highlights

SettingRecommendationWhy
Origin typeS3 REST endpoint + OACHTTPS + locked down
TTL (Min/Default/Max)60 s / 300 s / 86400 sBalance freshness vs. cache hit
Viewer ProtocolRedirect HTTP β†’ HTTPSSecurity
Allowed MethodsGET, HEAD (and OPTIONS if CORS)Minimize origin load
Lambda@Edge / FunctionsAuth rewrites, A/B testingEdge logic
Error Responses404 β†’ /index.html (for SPA)SPA fallbacks
Custom HeadersCache-Control: public, max-age=300, s-maxage=86400Fine-tune CDN vs. browser caching

Cache-hit ratio (CHR): If CHR = 0.90, then origin egress per 1 000 requests = 100

Egress = (1 000 Γ— (1 βˆ’ CHR)) β‰ˆ 100 requests β†’ significant cost savings at scale.


References

  1. AWS CloudFront Developer Guide – Edge Caching Strategies
  2. Next.js Docs – Incremental Static Regeneration
  3. AWS Certificate Manager – DNS Validation
  4. GitHub Actions Docs – Workflow Triggers

Join the Discussion

Share your thoughts and insights about this system.