Skip to main content
← All Tools · 🛠️ WebAssembly & Edge Computing

Netlify Edge Functions — Serverless Functions at the CDN Edge

Deno-powered edge functions on Netlify's global CDN — intercept requests, transform responses, and run custom logic at the edge without leaving the Netlify workflow.

Freemium Free: 3M edge function invocations/month; Pro/Team plans include higher limits
edge-computingserverlessnetlifydenojavascripttypescriptcdn

✅ Pros

  • + Deno runtime — TypeScript natively, Web APIs, npm package support
  • + Deep Netlify integration — same workflow as regular Netlify functions
  • + Request context includes geolocation, device type, account info
  • + Can run before or after Netlify's redirects and rewrites
  • + Netlify Dev supports local edge function development

⚠️ Cons

  • − Deno runtime limits npm package compatibility vs Node.js
  • − 50ms execution limit (soft) — designed for fast request modification
  • − Less control than Cloudflare Workers for complex applications
  • − Fewer edge locations than Cloudflare

Overview

Netlify Edge Functions are Deno-based functions that run at the CDN edge layer, before content is served to users. They integrate seamlessly with the Netlify build and deployment workflow, making them the natural choice for teams already using Netlify.

Creating an Edge Function

// netlify/edge-functions/greet.ts
import type { Config, Context } from "@netlify/edge-functions";

export default async (request: Request, context: Context): Promise<Response> => {
  const url = new URL(request.url);
  const name = url.searchParams.get("name") ?? "World";

  // Geo data from Netlify context
  const country = context.geo?.country?.code ?? "US";
  const city = context.geo?.city ?? "Unknown";

  return Response.json({
    message: `Hello, ${name}!`,
    location: `${city}, ${country}`,
  });
};

export const config: Config = {
  path: "/api/greet",
};

Netlify Configuration

# netlify.toml
[[edge_functions]]
path = "/api/greet"
function = "greet"

# Run on all routes
[[edge_functions]]
path = "/*"
function = "auth-check"

# Exclude static assets
[[edge_functions]]
path = "/*"
function = "middleware"
excludedPath = ["/static/*", "/*.js", "/*.css"]

Authentication Middleware

// netlify/edge-functions/auth.ts
import type { Config, Context } from "@netlify/edge-functions";

export default async (request: Request, context: Context) => {
  const url = new URL(request.url);

  // Protected routes
  if (!url.pathname.startsWith('/dashboard')) {
    return context.next();
  }

  const sessionCookie = context.cookies.get('session');

  if (!sessionCookie) {
    return Response.redirect(new URL('/login', url.origin));
  }

  try {
    // Verify session (use a lightweight JWT library)
    const session = await verifySession(sessionCookie.value);

    // Pass user info to origin via header
    const requestWithUser = new Request(request, {
      headers: {
        ...Object.fromEntries(request.headers),
        'x-user-id': session.userId,
      },
    });

    return context.next(requestWithUser);
  } catch {
    return Response.redirect(new URL('/login', url.origin));
  }
};

export const config: Config = { path: "/dashboard/*" };

Using npm Packages

// Netlify Edge Functions support npm packages via Deno's npm: prefix
import { Hono } from "npm:hono@4";
import { z } from "npm:zod@3";

const app = new Hono();

app.get("/api/data", async (c) => {
  return c.json({ timestamp: Date.now() });
});

export default app.fetch;
export const config: Config = { path: "/api/*" };

Context Object Features

export default async (req: Request, context: Context) => {
  // Geographic data
  console.log(context.geo?.country?.name);      // "United States"
  console.log(context.geo?.city);               // "New York"
  console.log(context.geo?.subdivision?.code);  // "NY"
  console.log(context.geo?.latitude);           // "40.7128"

  // Request cookies
  const theme = context.cookies.get('theme')?.value;

  // Account info (Netlify Identity)
  const user = context.account;

  // Modify and forward
  const response = await context.next();

  // Modify response
  response.headers.set('x-served-by', 'edge');
  return response;
};

Best For

  • Netlify-hosted sites and apps wanting to add edge logic without leaving the Netlify ecosystem — same CLI, same deploy commands, no separate worker configuration
  • A/B testing and feature flags at the edge — intercept requests, modify HTML, and set cookies before the response reaches the user
  • Auth middleware — validate JWT tokens or session cookies at the CDN edge to protect dashboard routes without origin round-trips
  • Geo-personalization — serve localized content, redirect to region-specific pricing pages, or block access by country using Netlify’s built-in geo context
  • Header manipulation — add security headers (CSP, HSTS, X-Frame-Options) globally across all routes without modifying the origin server

Netlify Edge Functions vs. Alternatives

Netlify Edge FunctionsCloudflare WorkersVercel Edge Functions
RuntimeDenoV8 isolates (JS/WASM)V8 isolates
Ecosystem lock-inNetlify onlyCloudflare onlyVercel only
Edge locationsNetlify’s network300+Vercel’s network
Execution limit50ms soft10-50ms CPU25ms CPU
Best forNetlify teams, Deno usersComplex edge apps, large scaleNext.js on Vercel

If you’re already on Netlify, Edge Functions are the natural choice for adding edge middleware. For platform-agnostic edge logic or if you need 300+ PoPs, Cloudflare Workers offers a more mature platform.