Netlify Edge
Netlify Edge Functions Micro-segmentation A/B Testing Personalization Geo-routing Deno TypeScript CDN Serverless Edge Network Latency Feature Flags Canary
| Use Case | Segment By | Action | Latency Impact | Complexity |
|---|---|---|---|---|
| A/B Testing | Cookie / Random | Rewrite URL | +1-2ms | ง่าย |
| Geo-routing | Country / Region | Rewrite / Redirect | +1-2ms | ง่าย |
| Personalization | Cookie / Header | Modify Response | +2-5ms | ปานกลาง |
| Feature Flags | User Group | Rewrite to variant | +1-3ms | ง่าย |
| Auth Gate | JWT / Session | Allow / Redirect | +3-10ms | ปานกลาง |
| Bot Protection | User-Agent / Rate | Block / Challenge | +1-2ms | ง่าย |
Edge Functions Setup
# === Netlify Edge Functions ===
# netlify/edge-functions/ab-test.ts
# import type { Context } from "https://edge.netlify.com";
#
# export default async (request: Request, context: Context) => {
# const url = new URL(request.url);
#
# // Skip non-page requests
# if (url.pathname.startsWith("/api") || url.pathname.includes(".")) {
# return;
# }
#
# // Check existing cookie
# const cookies = request.headers.get("cookie") || "";
# let variant = cookies.match(/ab_variant=(\w+)/)?.[1];
#
# // Assign variant if not set
# if (!variant) {
# variant = Math.random() < 0.5 ? "a" : "b";
# }
#
# // Rewrite to variant page
# const variantUrl = new URL(request.url);
# variantUrl.pathname = `/variants/`;
#
# const response = await context.rewrite(variantUrl);
#
# // Set sticky cookie (30 days)
# response.headers.append(
# "Set-Cookie",
# `ab_variant=; Path=/; Max-Age=2592000; SameSite=Lax`
# );
#
# return response;
# };
#
# export const config = { path: "/landing/*" };
# netlify/edge-functions/geo-route.ts
# import type { Context } from "https://edge.netlify.com";
#
# const REGIONAL_CONTENT: Record = {
# TH: "/th",
# JP: "/ja",
# KR: "/ko",
# CN: "/zh",
# };
#
# export default async (request: Request, context: Context) => {
# const country = context.geo?.country?.code || "US";
# const prefix = REGIONAL_CONTENT[country] || "/en";
#
# const url = new URL(request.url);
# if (!url.pathname.startsWith(prefix)) {
# url.pathname = ``;
# return context.rewrite(url);
# }
# };
#
# export const config = { path: "/*" };
from dataclasses import dataclass
@dataclass
class EdgeFunction:
name: str
trigger: str
segment: str
action: str
file_path: str
functions = [
EdgeFunction("A/B Test", "/landing/*", "Random 50/50 cookie", "Rewrite to variant", "netlify/edge-functions/ab-test.ts"),
EdgeFunction("Geo Route", "/*", "Country code", "Rewrite to locale", "netlify/edge-functions/geo-route.ts"),
EdgeFunction("Feature Flag", "/app/*", "User tier cookie", "Rewrite to feature variant", "netlify/edge-functions/feature-flag.ts"),
EdgeFunction("Auth Gate", "/admin/*", "JWT token", "Allow or redirect login", "netlify/edge-functions/auth-gate.ts"),
EdgeFunction("Bot Block", "/*", "User-Agent pattern", "Block or challenge", "netlify/edge-functions/bot-block.ts"),
]
print("=== Edge Functions ===")
for f in functions:
print(f" [{f.name}] Path: {f.trigger}")
print(f" Segment: {f.segment} | Action: {f.action}")
print(f" File: {f.file_path}")
Advanced Segmentation
# === Advanced Micro-segmentation ===
# Feature Flags with Edge
# netlify/edge-functions/feature-flag.ts
# const FLAGS: Record = {
# "new-checkout": { enabled: true, percentage: 20 },
# "dark-mode": { enabled: true, percentage: 100 },
# "ai-search": { enabled: true, percentage: 10 },
# };
#
# export default async (request: Request, context: Context) => {
# const url = new URL(request.url);
# const userId = getCookie(request, "user_id") || "anonymous";
#
# // Deterministic assignment based on userId hash
# const features: Record = {};
# for (const [flag, config] of Object.entries(FLAGS)) {
# if (!config.enabled) { features[flag] = false; continue; }
# const hash = simpleHash(`:`) % 100;
# features[flag] = hash < config.percentage;
# }
#
# // Inject features as header for downstream
# const response = await context.next();
# response.headers.set("x-features", JSON.stringify(features));
# return response;
# };
# Personalization based on segments
# netlify/edge-functions/personalize.ts
# export default async (request: Request, context: Context) => {
# const segment = getSegment(request, context);
# // segment: { tier: "premium", country: "TH", device: "mobile" }
#
# const response = await context.next();
# const html = await response.text();
#
# // Replace placeholders
# const personalized = html
# .replace("{{GREETING}}", segment.country === "TH" ? "สวัสดี" : "Hello")
# .replace("{{PRICING}}", getPricing(segment.tier, segment.country))
# .replace("{{CTA}}", segment.tier === "premium" ? "Upgrade Plan" : "Start Free");
#
# return new Response(personalized, response);
# };
@dataclass
class Segment:
name: str
criteria: str
size: str
content: str
conversion: str
segments = [
Segment("New Visitor", "No cookie first visit", "40%", "Welcome offer free trial", "2.1%"),
Segment("Returning Free", "Cookie tier=free", "35%", "Upgrade CTA features comparison", "3.5%"),
Segment("Premium User", "Cookie tier=premium", "15%", "Loyalty rewards new features", "8.2%"),
Segment("Mobile TH", "Device=mobile country=TH", "8%", "Thai content mobile optimized", "4.1%"),
Segment("Enterprise", "Cookie tier=enterprise", "2%", "Custom dashboard white-glove", "12.5%"),
]
print("\n=== User Segments ===")
for s in segments:
print(f" [{s.name}] Criteria: {s.criteria}")
print(f" Size: {s.size} | Content: {s.content}")
print(f" Conversion: {s.conversion}")
Monitoring
# === Edge Function Monitoring ===
# netlify.toml configuration
# [[edge_functions]]
# function = "ab-test"
# path = "/landing/*"
#
# [[edge_functions]]
# function = "geo-route"
# path = "/*"
#
# [build]
# command = "npm run build"
# publish = "dist"
@dataclass
class EdgeMetric:
metric: str
value: str
target: str
status: str
metrics = [
EdgeMetric("Edge Function Latency (p50)", "2.1ms", "<5ms", "Good"),
EdgeMetric("Edge Function Latency (p99)", "8.3ms", "<20ms", "Good"),
EdgeMetric("Invocations/day", "1.2M", "N/A", "Normal"),
EdgeMetric("Error Rate", "0.02%", "<0.1%", "Good"),
EdgeMetric("A/B Variant A Conversion", "3.2%", ">3%", "Good"),
EdgeMetric("A/B Variant B Conversion", "4.1%", ">3%", "Winner"),
EdgeMetric("Geo-route Cache Hit", "94%", ">90%", "Good"),
EdgeMetric("Feature Flag Coverage", "100%", "100%", "Good"),
]
print("Edge Function Metrics:")
for m in metrics:
print(f" [{m.status}] {m.metric}: {m.value} (Target: {m.target})")
best_practices = {
"Sticky Sessions": "ใช้ Cookie สำหรับ A/B ไม่ให้ User เปลี่ยน Variant",
"Fallback": "ถ้า Edge Function Error ให้ Fallback ไป Default Content",
"Cache": "Edge Function Response ควร Cache ถ้าเป็นไปได้",
"Monitoring": "ดู Latency Error Rate ทุก Function",
"Testing": "Test Edge Functions ด้วย netlify dev locally",
"Gradual Rollout": "เริ่ม 5% แล้วค่อยเพิ่ม ไม่ปล่อย 100% ทันที",
}
print(f"\n\nBest Practices:")
for k, v in best_practices.items():
print(f" [{k}]: {v}")
เคล็ดลับ
- Cookie: ใช้ Cookie สำหรับ Sticky A/B Testing
- Geo: ใช้ context.geo สำหรับ Regional Content
- Fallback: เตรียม Fallback เสมอเมื่อ Edge Function Error
- Local: Test ด้วย netlify dev ก่อน Deploy
- Gradual: Rollout Feature Flags ทีละ 5-10% ไม่ปล่อยทีเดียว
Netlify Edge Functions คืออะไร
Serverless Functions Edge Network Deno TypeScript A/B Testing Personalization Geo-routing Auth Header Redirect CDN Latency ต่ำ
Micro-segmentation คืออะไร
แบ่ง Traffic User กลุ่มย่อย Geographic Device Cookie Header AB Test Feature Flags Canary Regional Compliance Edge Latency ต่ำ
ทำ A/B Testing บน Edge อย่างไร
Edge Function Cookie Variant Random Rewrite URL Sticky Session Analytics Conversion Rate Traffic Split Real-time ไม่ต้อง Redeploy
Geo-routing ทำอย่างไร
context.geo Country City Region Timezone Rewrite Regional Content Redirect Domain Block IP Currency Compliance GDPR Cookie Consent
สรุป
Netlify Edge Functions Micro-segmentation A/B Testing Geo-routing Feature Flags Personalization Deno TypeScript CDN Latency Cookie Segment Production
