Using Netlify Edge Functions for Low‑Latency Request Manipulation
Learn how to deploy a Netlify Edge Function that adds a geo‑based header, with details on requirements, minimal design, trust boundaries, operational checks, and failure handling.
25 Mar 2026, 00:37 UTC

Problem: needing sub‑millisecond request logic without hitting the origin
Many sites require per‑request decisions—such as adding a geo‑based header, performing an A/B test, or checking an auth token—before the request reaches the origin server. Doing this in a central serverless function adds network round‑trip latency and can become a bottleneck under high traffic.
Requirements
- Execute logic as close to the end‑user as possible to reduce Time‑to‑First‑Byte (TTFB).
- Keep the function stateless; any persistent state must be external (e.g., Edge KV or a third‑party API).
- Maintain a clear trust boundary: the function must not read the local filesystem or access secrets stored with the site build.
- Provide observable operational checks (logs, headers, metrics) without a custom build step for the function code.
- Define failure behavior: if the function exceeds limits, the request should either fall back to the origin or return a defined error.
Smallest suitable design
Netlify Edge Functions meet these requirements by running a Deno‑based runtime on Netlify’s global edge nodes. The smallest design consists of:
- A function file written in TypeScript or JavaScript (no transpilation step required).
- A declaration in
netlify.tomlthat maps a URL path to the function. - The function receives the incoming request, inspects or mutates it, and returns a response.
Example: adding a geo‑country header
The following Edge Function reads the geo‑country supplied by Netlify’s request context and injects it as a response header.
// edge-functions/geo-header.ts
import type { Context } from '@netlify/edge-functions'
export default async (request: Request, context: Context): Promise => {
const country = request.geo?.country ?? 'unknown'
const headers = new Headers(request.headers)
headers.set('x-geo-country', country)
// Return a 200 OK with the new header; the body can be empty or you can forward to origin
return new Response(null, { status: 200, headers })
}
Corresponding netlify.toml entry:
[[edge_functions]]
path = "/api/geo-header"
function = "edge-functions/geo-header.ts"
Trust and data boundaries
The Edge runtime runs in a sandbox:
- The filesystem is read‑only; you cannot read
node_modulesor local files. - Environment variables are limited to those explicitly exposed in the site settings; build‑time secrets are not available.
- Only the incoming request, response, and a minimal set of web‑standard APIs (Fetch, Headers, Geo) are accessible.
- Stateful storage must go through Netlify Edge KV (key‑value with limited size) or an external API; the function itself cannot retain data across invocations.
This separation ensures that a compromised Edge Function cannot exfiltrate build artefacts or site secrets.
Operational checks
Verification can be performed without a custom build step:
- Run
netlify devlocally; the Edge Function is emulated and logs appear in the console. - Deploy to a preview branch with
netlify deploy --branch=previewand invoke the URL. - Inspect the response header using browser dev tools or
curl -I https://<site>.netlify.app/api/geo-header. The presence ofx-geo-countryconfirms execution. - Check the Netlify dashboard → Edge Functions → Logs for any runtime errors or duration metrics.
Because the runtime supports TypeScript natively, you can develop with IDE type‑checking and rely on Netlify to transpile at deployment time.
Failure modes
- Execution timeout: Edge Functions have a maximum of 50 ms CPU time (wall‑time may be higher). Exceeding this triggers a fallback to the origin or a 504 response, depending on the
fallbacksetting innetlify.toml. - Memory limit breach**: The default memory allocation is 128 MB. Going over results in a 502 error.
- Cold start**: Although minimized, the first request to a particular edge node may incur a few milliseconds of initialization latency.
These failures are visible in the Edge Functions logs; you can set up alerts on the Netlify UI for increased error rates.
Conditions that would change the design
The smallest Edge Function design is appropriate when:
- Logic remains stateless or can be delegated to Edge KV/external APIs.
- All required functionality can be expressed with the Deno standard library and web‑available APIs (no reliance on Node.js built‑ins like
fsorcryptothat are unavailable). - Execution time stays well under the 50 ms CPU budget.
If any of the following apply, you would need to reconsider the design:
- Need for durable, mutable state beyond the KV store’s size or throughput limits.
- Requirement for Node.js‑specific modules (e.g.,
aws-sdk) that lack Deno equivalents. - Business logic that routinely exceeds the CPU or memory limits (e.g., heavy image processing).
- Desire to maintain long‑lived connections such as WebSockets; Edge Functions currently only support HTTP request/response.
Practical verification checklist
- Deploy the function as shown above.
- Make a request from multiple geographic locations (e.g., using a VPN or a service like VPN Gate) and confirm that
x-geo-countrychanges accordingly. - Monitor the Edge Functions dashboard for any timeout or memory‑limit events; adjust the function or request limits if needed.
- Test failure by adding a synchronous loop that exceeds the CPU limit and verify that the request either falls back to the origin (if configured) or returns a 5xx status.
By following these steps you can confirm that the Edge Function is executing, manipulating requests as intended, and behaving predictably under both normal and failure conditions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.