Adding Dynamic Behavior to Static Sites with Netlify Edge Functions
Netlify Edge Functions let you run JavaScript at the CDN edge for personalization, geo‑routing, and A/B testing without managing servers. This post walks through a concrete geo‑based banner swap, highlights the 10 s/128 MB limits, and shows how to verify the deployment.
07 Apr 2026, 14:14 UTC

The Problem: Static Sites Need Dynamic Touches
You’ve built a fast, static site on Netlify. Now you need to show different content based on a visitor’s country, run a quick A/B test, or inject a personalized greeting—all without spinning up a separate backend server. Traditional serverless functions work, but they add latency because requests travel to a centralized region. Netlify Edge Functions let you run JavaScript at the CDN edge, keeping latency low while staying in the same deployment pipeline.
How Edge Functions Fit Into Your Netlify Site
Edge Functions are built into every Netlify site. You create a netlify/edge-functions directory (note: not functions—that’s for traditional serverless functions) and add a file that exports a default handler. The handler receives a Request object and returns a Response, using standard Web APIs. Netlify automatically packages, deploys, and routes requests to the edge network.
Key characteristics:
- Runs on Netlify’s global edge network (V8 isolates).
- Typical response time under 10 ms for warm invocations.
- Shares environment variables and secret handling with serverless functions.
- Maximum execution time: 10 seconds; memory limit: 128 MB.
- No filesystem or native OS access—only in‑memory data structures.
Worked Example: Geo‑Based Content Swap
Suppose you want to show a different hero banner for visitors from Germany. Create netlify/edge-functions/geo-banner.js:
export default async (request, context) => {
const country = request.headers.get('x-country') || 'US';
const html = await context.next(); // fetch the original HTML
const banner = country === 'DE'
? 'Willkommen in Deutschland!'
: 'Welcome to our site!';
return new HTMLRewriter()
.on('div#hero', { element: (el) => el.setInnerContent(banner) })
.transform(html);
};
Deploy with netlify deploy (or push to your connected Git repo). The function runs on every request to the associated path. You can limit it to a specific route via netlify.toml:
[[edge_functions]]
path = "/*"
function = "geo-banner"
After deployment, visit your site from a German IP (or set the x-country header via a browser extension) and verify the banner changes. No separate server, no extra DNS, no cold‑start penalty beyond the first edge invocation.
Trade‑offs and Limitations
- Cold starts: The first request to a rarely used function can add a few hundred milliseconds as the isolate spins up.
- Execution ceiling: Heavy computation, large payloads, or long‑running external API calls will hit the 10‑second/128‑MB limit and return a 502.
- No filesystem: You cannot read/write local files; use KV stores, external databases, or in‑memory caches.
- Debugging: Logs appear in the Netlify dashboard under Functions → Edge Functions, but you cannot attach a local debugger.
If your dynamic logic exceeds these bounds, fall back to traditional serverless functions (netlify/functions) or a dedicated backend.
Actionable Next Step
- Add a
netlify/edge-functionsfolder to your repo. - Write a tiny handler that reads a header (e.g.,
x-country) and rewrites a small piece of HTML usingHTMLRewriter. - Deploy and test with
curl -H "x-country: DE" https://your-site.netlify.app/. - Monitor the Edge Functions log tab for latency and error rates.
Start small—personalize a greeting or swap a banner. Once you’re comfortable with the constraints, expand to A/B testing, feature flags, or authentication checks at the edge.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.