Hermes Wiki
Developer/Compute/EdgeCompute/Fundamentals/edge-function-runtime-constraints

Edge Function Runtime Constraints

Concept

Edge compute platforms (Cloudflare Workers, Deno Deploy, Vercel Edge Functions) run application code inside points of presence distributed across hundreds of physical locations, rather than in a handful of centralized regions — the pitch is that a request from Sydney gets handled by a Sydney-adjacent PoP instead of round-tripping to us-east-1. That physical distribution is what buys the latency win no amount of backend optimization can match, but it's also exactly why edge runtimes can't just be "a smaller Lambda": running the same isolate model across hundreds of shared, multi-tenant locations forces much tighter resource limits than a traditional single-region serverless platform needs to enforce, and it forces a different execution model (V8 isolates, not per-invocation containers) to keep startup fast enough to be worth the trip.

The concrete constraints on Cloudflare Workers, as a representative example: 50ms of CPU time per request on the free tier, up to 30 seconds on paid plans by default, and opt-in up to 5 minutes (300,000ms) via a cpu_ms config value on paid plans. Critically, CPU time measures only time the V8 engine actually spends executing your code — parsing JSON, running loops, doing computation — and explicitly excludes time spent waiting on network I/O like a fetch() call or a KV store read. A function that awaits a slow upstream API for 10 seconds but does almost no computation itself can still run comfortably inside the CPU budget; a function that does a CPU-heavy JSON transform on a large payload can blow the 30-second default budget despite finishing in what feels like a fast request. Each isolate is also capped at 128MB of memory — an order of magnitude below what a traditional serverless function or container typically gets.

The runtime environment itself is narrower too: no persistent filesystem, no guarantee the same isolate survives between requests (so in-memory state can't be relied on as a cache across invocations without an explicit KV/Durable Object), and no full Node.js API surface — packages that assume fs, native addons, or other Node-specific internals often don't run unmodified.

Tradeoffs

Execution model Benefit Cost
Centralized region (traditional Lambda/backend) Full runtime surface, generous CPU/memory, persistent connections work normally Every request pays a network round-trip to the region, regardless of where the user is
Edge isolate (Workers/Deno Deploy/Vercel Edge) Runs physically close to the user, fast cold start (isolate, not container boot) Tight CPU (30-300s) and memory (128MB) caps, no filesystem, limited/no Node API surface
Edge for routing + region for compute (hybrid) Latency-sensitive decision (auth check, redirect, simple transform) happens close to the user; heavy work stays where it has room Two execution environments to reason about, deploy, and debug instead of one

The real tradeoff is where in the request path the constraints get paid. Push everything to the edge and you inherit its CPU/memory ceiling everywhere; keep everything centralized and every user outside your region pays the network latency the edge model exists to avoid. The hybrid pattern — lightweight, stateless logic at the edge, heavier compute behind it in a traditional region — is how most production edge usage actually resolves this rather than treating it as an all-or-nothing platform choice.

When to use / when not to

  • Use edge functions for latency-sensitive logic that's genuinely lightweight — auth/session checks, redirects, header rewrites, simple request/response transforms, A/B routing decisions.
  • A function that needs a large dependency tree, heavy CPU-bound computation, or a persistent database connection pool is a poor fit for the default CPU/memory ceiling — either raise the CPU budget explicitly (accepting the cost/latency tradeoff of doing more work per request) or keep that logic in a centralized service the edge function calls out to.
  • Don't assume in-memory state survives between requests on the same "instance" the way it might in a long-lived server process — isolates are not guaranteed to persist, and relying on that accidentally works in testing (low traffic, one isolate reused) and breaks in production (many isolates spun up under load).
  • Don't port a Node-dependent library to the edge without checking its actual runtime dependencies first — a library that "just imports fs" for an optional code path will fail at the edge even if that path is never hit in your usage.

Common pitfall

Treating the CPU-time budget as if it were the same as request latency, and being surprised when a request that "only takes 200ms end-to-end" still gets killed for exceeding CPU time. The two are different clocks: wall-clock latency includes time spent waiting on fetch()/KV, which doesn't count against the CPU budget at all, so a slow upstream call is nearly free from the CPU-limit's perspective — but a synchronous JSON.parse/transform over a large payload, or an unbounded loop, burns CPU time even if it finishes in milliseconds of wall-clock time. The fix is to profile CPU time specifically (most edge platforms expose this separately from total request duration), not to assume "the request felt fast" means "the request stayed inside its CPU budget."

Engineering Lens

Edge compute is a concrete case of a general principle: every execution environment encodes a bet about what workloads it's meant for, visible in exactly which resource it constrains tightly and which it leaves generous. A traditional serverless platform bets on "occasional cold starts are acceptable, give functions room to do real work"; an edge platform bets on "startup and CPU time must stay near-zero because the same isolate model runs across hundreds of shared locations, and any function doing genuinely heavy work belongs somewhere else." The judgment call that matters in a design review isn't "can this run at the edge" (almost anything technically can, until it hits the CPU ceiling) — it's whether the logic being pushed to the edge is actually latency-sensitive-but-lightweight, which is the one shape of workload the edge model's tradeoffs were built to reward.

Sources

Hermes Wiki