Edge Functions et l'Avenir du Serverless : Architecture Moderne en 2025
Salut HaWkers, le monde serverless a significativement évolué ces dernières années, et 2025 marque la consolidation des Edge Functions comme standard pour les applications haute performance. Si vous n'êtes pas encore familier avec l'edge computing ou voulez comprendre comment exploiter cette technologie, cet article vous guidera à travers les concepts et pratiques les plus importants.
Que sont exactement les Edge Functions ? Pourquoi offrent-elles une performance supérieure aux fonctions serverless traditionnelles ? Et comment pouvez-vous les implémenter dans vos projets ? Explorons tout cela avec des exemples pratiques.
Que Sont les Edge Functions
Les Edge Functions sont des fonctions serverless qui s'exécutent sur des serveurs distribués géographiquement, proches des utilisateurs finaux. Contrairement aux fonctions traditionnelles qui tournent dans des régions spécifiques, l'edge computing amène le calcul à la bordure du réseau.
Différence Entre Serverless Traditionnel et Edge
Serverless Traditionnel :
- S'exécute dans des régions spécifiques (us-east-1, eu-west-1, etc.)
- La latence dépend de la distance de l'utilisateur au datacenter
- Le cold start peut être significatif (centaines de ms à secondes)
- Environnement Node.js complet généralement disponible
Edge Functions :
- S'exécutent sur des centaines de points de présence globaux
- Latence constamment basse indépendamment de la localisation
- Cold start minimal (quelques millisecondes)
- Runtime optimisé basé sur V8 ou similaire
💡 Contexte : Pour un utilisateur en France accédant à une fonction en us-east-1, la latence réseau peut être de 100-200ms. Avec l'edge, cette latence tombe à 10-30ms.
Pourquoi les Edge Functions Dominent en 2025
L'adoption des edge functions a crû de façon exponentielle pour plusieurs raisons :
1. Performance Globale
Avec des serveurs dans plus de 300 emplacements autour du monde, les utilisateurs de n'importe où ont une latence similaire et basse.
2. Rapport Coût-Bénéfice
Malgré un coût par exécution similaire, la latence plus faible signifie moins de temps d'attente et une meilleure expérience, justifiant l'investissement.
3. Cas d'Usage Étendus
Initialement utilisées uniquement pour des redirections simples, elles supportent maintenant :
Cas d'usage modernes :
- Authentification et autorisation
- Personnalisation de contenu
- A/B testing
- Rate limiting
- Manipulation de headers
- Rendu côté serveur
- APIs complètes
4. Écosystème Mature
Des plateformes comme Cloudflare Workers, Vercel Edge Functions, Deno Deploy et AWS CloudFront Functions ont significativement mûri.
Implémenter des Edge Functions en Pratique
Voyons des exemples pratiques utilisant différentes plateformes.
Vercel Edge Functions
Parfaites pour les projets Next.js :
// pages/api/geo.ts ou app/api/geo/route.ts
import { NextRequest, NextResponse } from 'next/server';
export const config = {
runtime: 'edge', // Définit que c'est une edge function
};
export default function handler(req: NextRequest) {
// Informations de géolocalisation disponibles automatiquement
const country = req.geo?.country ?? 'Inconnu';
const city = req.geo?.city ?? 'Inconnue';
const region = req.geo?.region ?? 'Inconnue';
return NextResponse.json({
message: `Bonjour visiteur de ${city}, ${region}, ${country} !`,
latence: 'Cette réponse vient de l\'edge le plus proche de vous',
timestamp: new Date().toISOString(),
});
}Cloudflare Workers
L'une des plateformes les plus populaires pour l'edge :
// worker.ts
export interface Env {
MY_KV: KVNamespace;
}
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
const url = new URL(request.url);
// Rate limiting simple utilisant KV
const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown';
const rateLimitKey = `ratelimit:${ip}`;
const currentCount = await env.MY_KV.get(rateLimitKey);
const count = currentCount ? parseInt(currentCount) : 0;
if (count > 100) {
return new Response('Rate limit exceeded', { status: 429 });
}
// Incrémente le compteur avec TTL de 1 minute
ctx.waitUntil(
env.MY_KV.put(rateLimitKey, String(count + 1), {
expirationTtl: 60
})
);
// Logique principale
if (url.pathname === '/api/data') {
const data = await fetchDataFromOrigin();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}
return new Response('Not Found', { status: 404 });
},
};
async function fetchDataFromOrigin() {
// Simule la récupération de données
return { message: 'Données de l\'edge', timestamp: Date.now() };
}
Deno Deploy
Plateforme native pour l'edge avec Deno :
// server.ts
import { serve } from 'https://deno.land/std/http/server.ts';
interface RequestInfo {
method: string;
url: string;
userAgent: string | null;
region: string | null;
}
serve(async (request: Request): Promise<Response> => {
const requestInfo: RequestInfo = {
method: request.method,
url: request.url,
userAgent: request.headers.get('user-agent'),
region: Deno.env.get('DENO_REGION') ?? 'unknown',
};
// Routage simple
const url = new URL(request.url);
switch (url.pathname) {
case '/':
return new Response('Hello from Deno Edge!', {
headers: { 'content-type': 'text/plain' },
});
case '/api/info':
return new Response(JSON.stringify(requestInfo), {
headers: { 'content-type': 'application/json' },
});
case '/api/time':
const now = new Date();
return new Response(
JSON.stringify({
utc: now.toUTCString(),
iso: now.toISOString(),
region: requestInfo.region,
}),
{ headers: { 'content-type': 'application/json' } }
);
default:
return new Response('Not Found', { status: 404 });
}
});
Patterns Avancés avec les Edge Functions
Middleware d'Authentification
// middleware.ts (Next.js Edge Middleware)
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify } from 'jose';
const PUBLIC_PATHS = ['/', '/login', '/api/auth'];
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Permet les routes publiques
if (PUBLIC_PATHS.some(path => pathname.startsWith(path))) {
return NextResponse.next();
}
// Vérifie le token JWT
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
try {
const { payload } = await jwtVerify(token, JWT_SECRET);
// Ajoute les infos utilisateur aux headers
const response = NextResponse.next();
response.headers.set('x-user-id', payload.sub as string);
response.headers.set('x-user-role', payload.role as string);
return response;
} catch (error) {
// Token invalide
const response = NextResponse.redirect(new URL('/login', request.url));
response.cookies.delete('auth-token');
return response;
}
}
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico).*)',
],
};A/B Testing sur l'Edge
// Cloudflare Worker pour A/B testing
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Vérifie le cookie existant ou attribue une variante
const cookies = request.headers.get('Cookie') ?? '';
let variant = getCookie(cookies, 'ab-variant');
if (!variant) {
// Attribue une variante aléatoirement (50/50)
variant = Math.random() < 0.5 ? 'A' : 'B';
}
// Modifie la réponse basée sur la variante
const response = await fetch(request);
const html = await response.text();
let modifiedHtml = html;
if (variant === 'B') {
// Applique les changements de la variante B
modifiedHtml = html.replace(
'<button class="cta">Acheter Maintenant</button>',
'<button class="cta-new">Ajouter au Panier</button>'
);
}
const newResponse = new Response(modifiedHtml, response);
// Définit le cookie pour maintenir la cohérence
newResponse.headers.append(
'Set-Cookie',
`ab-variant=${variant}; Path=/; Max-Age=604800`
);
return newResponse;
},
};
function getCookie(cookies: string, name: string): string | null {
const match = cookies.match(new RegExp(`${name}=([^;]+)`));
return match ? match[1] : null;
}
Limitations et Considérations
Ce Que les Edge Functions Ne Font Pas Bien
Limitations importantes :
- Temps d'exécution limité (généralement 30s max, certains 50ms)
- Mémoire restreinte (128MB typique)
- Pas d'accès au filesystem
- APIs limitées (pas de Node.js natif complet)
- Connexions longue durée problématiques
Quand Utiliser le Serverless Traditionnel
Préférez le serverless traditionnel pour :
- Traitement intensif CPU
- Opérations de base de données complexes
- Tâches de longue durée
- Quand vous avez besoin de l'écosystème Node.js complet
- Traitement de gros fichiers
Architecture Hybride
La meilleure approche combine généralement edge et serverless :
Utilisateur
↓
Edge Function (authentification, cache, personnalisation)
↓
Serverless Function (logique métier, base de données)
↓
Base de Données / Services
Comparatif des Plateformes
| Plateforme | Cold Start | Emplacements | Langages | Usage Gratuit |
|---|---|---|---|---|
| Cloudflare Workers | ~0ms | 300+ | JS/TS, Rust, WASM | 100k req/jour |
| Vercel Edge | ~1ms | 100+ | JS/TS | Selon plan |
| Deno Deploy | ~1ms | 35+ | JS/TS, WASM | 1M req/mois |
| AWS CloudFront | ~5ms | 400+ | JS | Selon usage |
| Fastly Compute | ~5ms | 70+ | JS, Rust, WASM | Selon usage |
Choisir la Bonne Plateforme
Cloudflare Workers :
- Meilleur pour les applications standalone
- Écosystème le plus mature (KV, D1, R2)
- Prix compétitifs
Vercel Edge :
- Idéal pour les projets Next.js
- Intégration parfaite avec le framework
- Edge Middleware puissant
Deno Deploy :
- Excellent pour ceux qui préfèrent Deno
- Deploy via GitHub simple
- TypeScript first-class
Meilleures Pratiques
1. Cache Agressif
// Implémentez du cache pour les réponses qui peuvent être cachées
export default {
async fetch(request: Request): Promise<Response> {
const cacheKey = new Request(request.url, request);
const cache = caches.default;
// Vérifie le cache d'abord
let response = await cache.match(cacheKey);
if (!response) {
response = await fetch(request);
// Clone pour cacher
response = new Response(response.body, response);
response.headers.set('Cache-Control', 'public, max-age=3600');
// Cache en arrière-plan
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
return response;
},
};2. Gestion des Erreurs Robuste
export default {
async fetch(request: Request): Promise<Response> {
try {
return await handleRequest(request);
} catch (error) {
console.error('Edge function error:', error);
// Retourne une réponse d'erreur conviviale
return new Response(
JSON.stringify({
error: 'Internal Error',
message: 'Something went wrong',
}),
{
status: 500,
headers: { 'Content-Type': 'application/json' },
}
);
}
},
};3. Monitoring et Observabilité
// Ajoutez du logging structuré
interface LogEntry {
timestamp: string;
level: 'info' | 'warn' | 'error';
message: string;
metadata?: Record<string, unknown>;
}
function log(entry: LogEntry) {
console.log(JSON.stringify(entry));
}
export default {
async fetch(request: Request): Promise<Response> {
const startTime = Date.now();
const response = await handleRequest(request);
log({
timestamp: new Date().toISOString(),
level: 'info',
message: 'Request handled',
metadata: {
url: request.url,
method: request.method,
status: response.status,
duration: Date.now() - startTime,
},
});
return response;
},
};
Conclusion
Les Edge Functions représentent une évolution significative dans l'architecture serverless, offrant une latence constamment basse pour les utilisateurs globaux. En 2025, elles sont devenues un composant essentiel pour les applications qui priorisent la performance.
La clé est de comprendre quand utiliser l'edge versus le serverless traditionnel. Pour l'authentification, la personnalisation, le rate limiting et les réponses rapides, l'edge est idéal. Pour le traitement lourd et la logique métier complexe, le serverless traditionnel reste le bon choix.
La combinaison des deux offre le meilleur des deux mondes : des réponses rapides sur l'edge avec la puissance de traitement du backend quand nécessaire.
Si vous voulez approfondir les architectures modernes, je recommande de jeter un œil à un autre article : PWAs avec JavaScript : La Révolution des Applications Web où vous découvrirez comment construire des expériences web modernes et performantes.

