#Next.js#DevOps

Edge Computing and CDNs: Moving Compute Closer to Users

Users in Asia, servers in the US, and 300 ms of latency? CDNs cache static assets, while Edge Functions run logic at the edge so requests are handled nearby. This article explains CDN caching, Edge Functions (Cloudflare Workers/Vercel Edge), when to move logic from the origin to the edge, and the limits of doing so.

Key Points

  • Topic Focus: Next.js、DevOps
  • Suitable for: indie hackers, full-stack engineers, AI application developers
  • Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Author @admin·Published July 26, 2026·Updated July 26, 2026

Edge Computing and CDNs: Moving Compute Closer to Users

First, a frustrating fact of physics: light travels through fiber at roughly 200,000 kilometers per second.

This means that when a user in Asia requests data from a server in the United States, crossing the Pacific alone takes 60–100 ms each way, with round-trip latency starting at 150–250 ms. That accounts only for physical transmission, before TLS handshakes, server-side processing, or database queries. You can optimize your code, add indexes, and deploy Redis, but once RTT exceeds 200 ms, that transoceanic fiber consumes half the benefit of all your backend work.

So the central premise of frontend performance engineering over the past decade can be reduced to one sentence: if you cannot make light travel faster, move content and compute closer to users.

That is the essence of CDNs and edge computing. This article discusses them together because they apply the same idea at different layers: CDNs move "content," while Edge moves "compute."

1. The Physical Limits of Latency: Why Move Closer to Users

Start with a mental model. The latency involved when a user visits a webpage consists roughly of four parts:

text
[User] --(network RTT)--> [Server] --(processing)--> [DB] --(response)--> [User]
           ↑ physical latency       ↑ compute latency   ↑ I/O latency

You can optimize only the parts within your stack: compute latency through better code and faster runtimes such as V8, Rust, and caching; I/O latency through indexes, connection pools, and read replicas. But network RTT depends on geography. You cannot shorten the physical distance from Shanghai to Frankfurt.

The only way to "cheat" is to move the server closer.

  • Move a static copy closer → CDN
  • Move a piece of compute logic closer → Edge Function

Together, these two approaches form the entire foundation of modern edge architecture.

2. CDNs: Caching Static Assets Around the World

A CDN (Content Delivery Network) does something straightforward: it deploys many edge nodes, or POPs (Points of Presence), around the world. Requests are routed to a nearby node based on geography. If the node has the requested asset cached, it returns it immediately; otherwise, it fetches it from the central origin server.

text
                [Central origin]  (deployed on Vercel / in your own data center)
                        ^
                        | Origin fetch (on a miss)
                        v
   [Singapore POP]   [Frankfurt POP]   [US West POP]   [São Paulo POP]
          ^                 ^                 ^                ^
          |                 |                 |                |
   Asian users fetch   European users   North American    South American
       locally          fetch locally   users fetch locally  users fetch locally

The real challenge with a CDN is not "caching," but cache policy. There are three core concepts:

1. Cache Key. This is usually URL + Host + selected Headers. Version parameters such as ?v=123 and query parameters such as /api/user?id=5 both affect cache hits. A common pitfall is serving the same image with a different signed ?token= value for every user, causing the CDN to cache a separate copy per user. Either exclude the signature from the cache key or use Cookie-based authentication instead.

2. TTL (Time-To-Live). This determines how long an asset remains on a node. HTML may live for tens of seconds, a hashed asset such as _next/static/chunk-abc.js for a year, and API JSON for a few seconds or not at all. In Next.js, the Cache-Control header and revalidate duration are both, fundamentally, ways to manage TTL.

3. Invalidation. The best-known saying in the CDN world is Phil Karlton's: "There are only two hard things: cache invalidation and naming things." TTL lets a cache expire naturally, but when content changes, you need to purge the old version proactively. Cloudflare Cache Tags, Fastly Surrogate Keys, and Vercel's revalidateTag all serve this purpose: tag resources, then purge them in batches by tag when publishing.

Practical advice: give content-hashed static assets a long immutable cache lifetime, while using short TTLs plus active invalidation for HTML and APIs. This is essentially what the Next.js App Router does for you by default: _next/static/* is cached permanently, while pages use ISR according to their revalidate setting.

3. Edge Functions: Moving Compute to the Edge Too

CDNs solve the static-asset problem, but what about dynamic requests such as signing in, placing an order, or generating personalized recommendations? Traditionally, they had to reach the central origin, requiring another transoceanic round trip.

The answer from Edge Functions is: deploy a piece of JS/TS logic to edge nodes worldwide, execute each request nearby, and contact the central origin only when central data is genuinely required.

The three major players are:

  • Cloudflare Workers: Based on V8 isolates, not containers or VMs, with virtually zero cold-start time. Once deployed, code runs across more than 300 nodes worldwide. The runtime uses standard Web APIs (fetch / Request / Response), so development feels similar to writing a Service Worker.
  • Vercel Edge Functions / Middleware: Also based on V8 isolates, deeply integrated with Next.js, and executed on Vercel's Edge Network. Next.js middleware.ts uses the Edge Runtime by default.
  • Deno Deploy: Deno's official edge platform, also based on the isolate model and compatible with Web-standard APIs.

Architecture overview:

text
   User request
        |
        v
  [Nearest edge POP]
        |
        ├── Edge Function executes (lightweight logic)
        |     - Authentication / URL rewrites / A-B routing
        |     - Read KV / D1 / Edge Config (edge storage)
        |
        ├── Hit?  --> Return directly (no origin request)
        |
        └── Miss --> Central origin API / DB

The key distinction is in the first stage: a traditional architecture says "the edge only forwards requests, and all logic runs centrally"; an edge architecture says "the edge processes requests first and contacts the origin only when it cannot handle them." For logic such as authentication and redirects that can finish within 1 ms, reducing latency from a 200 ms RTT to 5 ms delivers an order-of-magnitude improvement in user experience.

4. What Belongs at the Edge

Not every kind of logic belongs at the edge. Edge-friendly workloads are lightweight, fast, stateless, read-heavy, and write-light.

  • Routing and redirects: Geographic routing, such as sending users in China to a cn domain; /old-path → /new-path; and Cookie-based routing for gradual rollouts. This is the most typical use of Next.js Middleware.
  • A/B testing: Route users by hashing their user IDs and decide which version to render at the edge, with the central origin entirely unaware of the decision.
  • Authentication and bot blocking: Validate JWTs, inspect session Cookies, and block crawlers. Return 401 immediately when validation fails without contacting the origin, saving central compute and bandwidth.
  • Simple API aggregation: Combine results from several backend APIs at the edge and return them together, reducing client round trips.
  • Lightweight SSR / personalized pages: Render the page shell at the edge and retrieve only the data from the central origin.
  • Edge Config / KV reads: High-read, low-write data such as feature flags and configuration switches is ideal for edge KV storage.

A useful rule of thumb: if this logic moves to the edge, can it finish within 50 ms without querying the central database? If yes, put it there. If not, keep it at the origin.

5. What Does Not Belong at the Edge

This section matters even more than the previous one because many teams adopt edge computing because it is fashionable, then retreat after encountering its pitfalls. Edge runtimes impose hard constraints. Remember these boundaries:

1. No compute-intensive work. The Edge Runtime uses isolates, not a complete Node.js environment, and strictly limits CPU time. Cloudflare allows 10–50 ms of CPU time by default and terminates execution when that limit is exceeded. Image processing, video transcoding, sorting large lists, and complex recommendation models all belong at the origin.

2. No large dependencies. A single compressed Vercel Edge Function deployment usually has a 1–4 MB limit, while Cloudflare Workers allows 1 MB on the free plan and 10 MB on paid plans. Importing all of lodash, an ORM, and a Markdown parser can already exceed the limit. Next.js Edge Runtime exposes only a limited subset of Web-standard APIs; fs, child_process, and most native Node.js modules are unavailable.

3. No persistent connections. Edge environments follow a request-response model. WebSocket, long polling, and long-lived SSE connections are unreliable at the edge. Use a dedicated central service or a specialized model such as Durable Objects when persistent connections are required.

4. No strongly consistent database access. Edge nodes are still physically far from the central database. If every Edge Function invocation has to query the primary database for a strongly consistent transaction, the proximity advantage disappears. You have merely replaced user → origin latency with edge → origin latency. Edge reads should use edge storage such as KV / D1 / Turso / Edge Config, where eventual consistency is sufficient; strongly consistent writes should always remain at the origin.

5. No libraries that depend on the Node.js ecosystem. Code using Buffer.slow, certain node:crypto algorithms, sharp, or mongoose will fail directly in the Edge Runtime. Always run a build before migrating.

In short: the edge is for "gatekeepers" and "couriers," not "factories."

6. Combining CDN and Edge: Faster Dynamic Requests and Cheaper Static Delivery

A real production architecture does not choose one or the other; it combines them in layers. A mature Next.js application usually looks like this:

text
                          User request
                               |
                      [Global edge nodes]
                     /                   \
       Static assets (_next/static)   Dynamic requests (pages/APIs)
                  |                           |
             [CDN cache]                [Edge Middleware]
          Return immediately on hit    Authentication / routing / rewrites
           (1 year, immutable)                    |
                                          [Edge SSR or origin fetch]
                                          /                       \
                                  ISR hit?                    Central origin
                            Return cached static HTML        Access central DB
                                                          Run heavy business logic

Layering principles:

  • Layer 1, CDN: All content-hashed static assets use long-lived CDN caching and never contact the origin.
  • Layer 2, Edge Middleware: Perform authentication, A/B testing, and geographic routing at the edge. Terminate failed or simple requests locally.
  • Layer 3, Edge SSR / ISR: Render pages at edge nodes or read them from the ISR cache. Render once, then serve subsequent requests from the cache.
  • Layer 4, central origin: Only requests that genuinely need the primary database or heavy business logic reach the origin.

The result is that 90% of requests are completed at the edge, and the central server sees only the remaining 10% of "heavy work." That is where the ROI of edge architecture comes from.

7. Next.js Edge Runtime: What It Can Run and What It Should Run

Next.js exposes edge capabilities through several APIs. Understand the trade-offs before choosing one:

  • middleware.ts: Always runs in the Edge Runtime. Keep it limited to pure logic such as authentication, rewrites, redirects, and Header manipulation. Do not put heavy work there. It runs before every request, so adding even one millisecond slows down the entire site.
  • Edge SSR: Add export const runtime = 'edge' to a page to render it at edge nodes. The benefit is low latency worldwide; the drawback is that it cannot run ISR (ISR is restricted in Edge mode), and dependencies are limited to Web-standard APIs.
  • Node.js Runtime (default): Provides complete Node.js capabilities and supports ISR and all npm packages, but runs only in the central region.

Practical trade-offs:

  • Pages such as homepages, marketing pages, and sign-in pages that have global traffic, lightweight data, and strong personalization → Edge SSR.
  • Blogs, documentation, and product-detail pages with stable content that can be statically generated → Node Runtime + ISR, with the generated HTML delivered through the CDN.
  • Admin systems, analytics, and complex forms → Keep them in the central Node Runtime.

Do not use Edge merely for the sake of using "Edge." A useful approach is to measure latency first. If 90% of your users are in one region, a central deployment is enough and edge computing is overengineering. If your users span three continents and Time to First Byte (TTFB) frequently exceeds 300 ms, edge computing is essential.

Summary

Reduce the entire approach to a few practical rules:

  1. Physical latency cannot be fixed; it can only be bypassed. The speed of light is a hard limit, so the optimization direction is always to move closer to users: CDNs move content, while Edge moves compute.
  2. The core of a CDN is cache policy, not caching itself. Cache keys, TTL, and invalidation (Cache Tag / revalidateTag) are the real engineering challenges. Give hashed assets permanent caching, and use short TTLs plus active invalidation for HTML and APIs.
  3. Edge Functions are suitable as gatekeepers, not factories. Put authentication, routing, rewrites, lightweight SSR, and KV reads at the edge. Keep intensive computation, large dependencies, persistent connections, and strongly consistent database access at the origin.
  4. Edge runtimes have hard limits. Validate CPU time, bundle size, and the available API subset in advance. Next.js Edge Runtime is not a browser, and it is certainly not Node.js.
  5. Production architecture is a layered combination, not an either-or choice. CDN for static assets → Edge Middleware for authentication → Edge SSR/ISR for rendering → central DB for heavy logic, completing 90% of requests at the edge.

Key takeaway: Edge computing does not move the entire backend to every corner of the world. It stations "gatekeepers" and "couriers" on every street corner, while the heavy work still returns to the factory.

Related

Related Content