Supabase Edge Functions en pratique : runtime Deno et déploiement edge mondial

Sur le tableau de bord de monitoring, la ligne rouge clignote — le temps de réponse API atteint 2,3 secondes.
L’utilisateur est au Japon, le serveur en Ohio. Le aller-retour seul prend 120 ms, sans compter la requête base de données et la logique métier. Comment ne pas être lent ?
« Et si on essayait les edge functions ? » Un collègue m’envoie ça sur Slack.
J’étais sceptique. Des edge functions ? Ce n’est pas juste du code exécuté ailleurs ? Quelle différence ça peut faire ? Puis j’ai testé — et j’ai été surpris. Cold start 120 ms, réponse en 47 ms. Même logique, déplacée d’Ohio vers un nœud edge à Tokyo : presque 5× plus rapide.
Supabase Edge Functions s’exécute sur le runtime Deno, au plus près des utilisateurs via le réseau edge mondial. Cet article explique pourquoi c’est si rapide, la différence entre Deno et Node.js, comment monter une Edge Function de zéro, et comment choisir face à Cloudflare Workers.
1. Concepts clés : qu’est-ce qu’une Edge Function, et pourquoi c’est rapide
En bref, une Edge Function déplace votre code d’un « serveur central » vers un « nœud edge ».
Avant, quand vous déployiez une fonction Lambda, elle tournait dans une région fixe (US East, Europe, etc.). Un utilisateur à Tokyo envoyait une requête ; les données traversaient l’océan jusqu’à l’Est des États-Unis, revenaient traitées. La distance physique fixe une limite de latence — la lumière n’est pas infinie.
Edge Functions inverse la logique. Votre code est empaqueté dans un format compact appelé ESZip, puis distribué automatiquement sur des dizaines de nœuds edge mondiaux. Une requête depuis Tokyo s’exécute à Tokyo — la latence transocéanique disparaît.
Qu’est-ce qu’ESZip ?
Format de bundle développé par l’équipe Deno. Contrairement à un bundle JavaScript classique, ESZip embarque aussi le graphe complet des dépendances de modules. Résultat : au démarrage, plus besoin de télécharger des dépendances sur le réseau — tout est dans un seul fichier. Le cold start passe de « téléchargement + résolution + exécution » à « décompression + exécution ».
Modèle d’exécution Isolate
Supabase Edge Functions tourne dans un V8 Isolate, pas dans un conteneur ou une VM traditionnelle. Un Isolate, c’est comme un conteneur Worker ultra-léger. Un processus peut héberger des dizaines d’Isolates, chacun traitant une requête. Plus léger qu’un conteneur, plus rapide au démarrage.
D’après la documentation Supabase, le temps CPU maximal d’un Isolate est de 400 s (limite souple + limite stricte). Ça paraît énorme, mais les edge functions ne sont pas faites pour le gros calcul — validation JWT, proxy, logique légère. Le travail lourd reste sur le serveur central.
Voici la Edge Function la plus simple :
// Exemple minimal de Edge Function
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
Deno.serve(async (req) => {
const { name } = await req.json()
const data = { message: `Hello ${name}!` }
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" }
})
})
Ce code tourne sur un nœud edge. La requête entre, Deno.serve la traite, la réponse repart — le tout au nœud le plus proche de l’utilisateur.
2. Runtime Deno : la « version sécurisée » de Node.js
La première fois que j’ai entendu parler de Deno, j’ai eu la même question : Node.js est si mature, pourquoi un nouveau runtime ?
La réponse est simple : Node.js a été conçu trop tôt ; beaucoup de problèmes sont apparus après coup.
Différence de sécurité
Node.js fait confiance par défaut. Votre code veut lire le disque ? OK. Se connecter au réseau ? Libre. Exécuter des commandes système ? Possible. Une dépendance malveillante peut tout faire.
Deno inverse la logique. Par défaut, le code est enfermé dans une sandbox : pas de lecture disque, pas de réseau, pas de commandes système. Pour obtenir une permission, il faut la déclarer explicitement :
# Permission réseau
deno run --allow-net server.ts
# Lecture/écriture de fichiers
deno run --allow-read --allow-write file_ops.ts
# Toutes les permissions (à utiliser avec prudence)
deno run -A everything.ts
En environnement edge, c’est crucial. Votre fonction tourne sur des dizaines de nœuds mondiaux ; une faille a un impact massif.
Différence de cold start
Données mesurées. Même code sur Deno Deploy et AWS Lambda :
| Runtime | Cold start |
|---|---|
| Deno Deploy | ~120 ms |
| AWS Lambda (Node.js) | 300-500 ms |
Facteur 3. Les raisons sont complexes, mais le cœur du problème : Deno n’a pas le bagage historique de Node.js — CommonJS, résolution require, parcours de node_modules. ESZip + TypeScript natif suppriment une montagne de surcoût au démarrage.
Évolution du système de modules
Node.js utilise CommonJS : require() pour charger les modules, npm, package.json, dossier node_modules. Sur un gros projet, ce dossier peut peser des centaines de Mo.
Deno adopte directement le standard ESM. Pas de npm, pas de package.json, pas de node_modules. Import par URL :
// Import direct depuis une URL
import { serve } from "https://deno.land/[email protected]/http/server.ts"
// Ou via JSR (registre de packages Deno)
import { cors } from "jsr:@hono/hono/cors"
Au premier lancement, Deno télécharge et met en cache les modules localement. Ensuite, chaque démarrage lit le cache — plus de téléchargement réseau.
TypeScript sans configuration
Avec Node.js, TypeScript exige ts-node ou webpack/vite/esbuild, plus un tsconfig.json. Deno supporte TypeScript nativement :
deno run hello.ts
Compilation et vérification de types intégrées au runtime. Expérience de développement bien plus propre.
Question du lock-in fournisseur
C’était aussi ma crainte : avec Supabase Edge Functions, suis-je prisonnier de leur plateforme ?
Pas forcément. Deno est open source, et l’Edge Runtime de Supabase aussi (code sur GitHub). En théorie, vous pouvez faire tourner Edge Runtime sur votre propre serveur. Le coût d’exploitation d’un réseau edge mondial, en revanche, reste à votre charge. Techniquement, vous n’êtes pas « coincé ».
3. Mise en pratique : votre première Edge Function en 10 minutes
La théorie ne suffit pas — il faut essayer.
J’ai suivi la doc officielle, de l’installation au déploiement : moins de 10 minutes. Voici le flux complet :
Étape 1 : installer Supabase CLI
npm install -g supabase
Vérifiez la version :
supabase --version
# Sortie du type : 1.200.0
Étape 2 : initialiser le projet
Si vous avez déjà un projet Supabase, initialisez dans le répertoire :
supabase init
Cela crée un dossier supabase avec config.toml.
Étape 3 : créer une Edge Function
supabase functions new hello-world
Un fichier index.ts apparaît dans supabase/functions/hello-world/ :
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
Deno.serve(async (req) => {
const data = {
message: "Hello from Edge Function!"
}
return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" }
})
})
Adaptez la logique. Par exemple, recevoir un paramètre name et renvoyer un message :
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
Deno.serve(async (req) => {
// Accepter uniquement POST
if (req.method !== "POST") {
return new Response("Method not allowed", { status: 405 })
}
try {
const body = await req.json()
const name = body.name || "Stranger"
return new Response(JSON.stringify({
message: `Hey ${name}, welcome to the edge!`,
timestamp: new Date().toISOString()
}), {
headers: { "Content-Type": "application/json" }
})
} catch (err) {
return new Response(JSON.stringify({ error: "Invalid JSON" }), {
status: 400,
headers: { "Content-Type": "application/json" }
})
}
})
Étape 4 : test local
Supabase CLI permet d’exécuter les Edge Functions en local :
supabase functions serve --no-verify-jwt
Service local sur le port 54321 par défaut. Test avec curl :
curl -X POST http://localhost:54321/functions/v1/hello-world \
-H "Content-Type: application/json" \
-d '{"name":"Easton"}'
# Retour :
# {"message":"Hey Easton, welcome to the edge!","timestamp":"2026-05-03T14:30:00.000Z"}
--no-verify-jwt désactive la validation JWT pour faciliter les tests locaux. En production, activez-la.
Étape 5 : déploiement mondial
Une fois les tests locaux OK, déployez sur le réseau edge Supabase :
# Connexion (si pas déjà fait)
supabase login
# Lier votre projet
supabase link --project-ref <your-project-id>
# Déployer la fonction
supabase functions deploy hello-world
Supabase distribue la fonction sur les nœuds edge mondiaux. Consultez les logs de déploiement et l’URL dans le Dashboard.
Étape 6 : test d’appel
URL de la fonction déployée :
https://<project-id>.supabase.co/functions/v1/hello-world
Appel avec curl :
curl -X POST https://<project-id>.supabase.co/functions/v1/hello-world \
-H "Authorization: Bearer <anon-key>" \
-H "Content-Type: application/json" \
-d '{"name":"World"}'
Notez l’en-tête Authorization. Supabase Edge Functions valide le JWT par défaut — utilisez la clé anon du projet ou un token JWT utilisateur.
Au-delà de la démo, les cas d’usage sont nombreux :
Traitement de webhooks
Par exemple, un webhook Stripe après paiement réussi — une Edge Function reçoit et écrit en base :
// supabase/functions/stripe-webhook/index.ts
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
import { createClient } from "jsr:@supabase/supabase-js@2"
Deno.serve(async (req) => {
// Vérification de la signature Stripe (simplifiée ici ; en prod, validation HMAC)
const event = await req.json()
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
)
if (event.type === "payment_intent.succeeded") {
const payment = event.data.object
await supabase.from("payments").insert({
id: payment.id,
amount: payment.amount,
customer_id: payment.customer,
created_at: new Date().toISOString()
})
}
return new Response(JSON.stringify({ received: true }), {
headers: { "Content-Type": "application/json" }
})
})
Proxy API
Une API tierce nécessite une clé que vous ne voulez pas exposer au frontend ? Proxy via Edge Function :
// supabase/functions/openai-proxy/index.ts
Deno.serve(async (req) => {
const body = await req.json()
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${Deno.env.get("OPENAI_API_KEY")}`,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
})
return new Response(response.body, {
headers: { "Content-Type": "application/json" }
})
})
Le frontend appelle votre Edge Function ; la clé API reste sur le nœud edge.
4. Choix : Supabase vs Cloudflare Workers
En edge computing, la question revient souvent : Cloudflare Workers ou Supabase Edge Functions ?
Ce ne sont pas des concurrents directs. Le scénario dicte le choix.
Comparaison des performances
Sur le cold start, Cloudflare Workers est plus rapide : ~30 ms officiellement, contre ~120 ms pour Supabase Edge Functions.
Pourquoi ? Le runtime Workers de Cloudflare est propriétaire, optimisé pour le edge. Supabase utilise Deno — rapide, mais avec une couche de compilation TypeScript en plus.
En pratique ? Pour la plupart des cas, 120 ms vs 30 ms passent inaperçus — la latence réseau fluctue davantage. Pour le trading haute fréquence ou les enchères temps réel, Cloudflare Workers convient mieux.
Comparaison de l’intégration
Point fort de Supabase : avec Edge Functions, connexion directe à Postgres du même projet, Auth, Storage. Variables d’environnement injectées automatiquement.
Cloudflare Workers exige de gérer la connexion base vous-même — D1 (SQLite edge) ou base externe, avec un peu de configuration en plus.
Lock-in fournisseur
Cloudflare Workers : runtime propriétaire. Le code ne tourne que chez Cloudflare ; changer de plateforme implique des modifications.
Supabase Edge Functions : Deno open source. Même code portable vers Deno Deploy ou Edge Runtime auto-hébergé. Le réseau edge Supabase, lui, ne se déplace pas — mais le runtime ne vous enferme pas.
Comparaison des écosystèmes
Cloudflare Workers est plus mature (2017) : outils, frameworks, communauté. Hono, Remix supportent Workers.
Supabase Edge Functions (2022) est plus récent, mais hérite des bibliothèques Deno standard.
Recommandations
| Votre situation | Recommandation |
|---|---|
| Déjà sur Supabase (Auth, Database, Storage) | Supabase Edge Functions |
| Edge pur, sans base de données | Cloudflare Workers |
| Crainte du lock-in | Supabase Edge Functions (Deno open source) |
| Cold start extrême (<50 ms) | Cloudflare Workers |
| Postgres en edge | Supabase Edge Functions |
Mon approche actuelle : hybride. Cloudflare Workers pour reverse proxy et cache frontend ; Supabase Edge Functions pour Auth et opérations base de données. Chaque plateforme à sa force.
5. Pièges rencontrés et bonnes pratiques
Les erreurs que j’ai faites — pour que vous les évitiez.
Piège 1 : utiliser des packages Node.js
J’ai voulu axios pour les requêtes HTTP : import axios from "axios". Déploiement → erreur : module introuvable.
Edge Functions = Deno, pas Node.js. Les packages npm ne passent pas. Utilisez des packages compatibles Deno ou l’API fetch native — largement suffisante :
// N'utilisez pas axios
// import axios from "axios" // erreur au déploiement
// Utilisez fetch
const response = await fetch("https://api.example.com/data", {
method: "GET",
headers: { "Authorization": "Bearer xxx" }
})
const data = await response.json()
Alternative Deno proche d’axios : ky.
Piège 2 : fonction trop longue, arrêt forcé
Une fonction batch parcourant des milliers d’enregistrements. OK en local, coupée à 30 s en production.
Edge Functions a une limite CPU. D’après la doc, 400 s max par Isolate (souples + strictes). Au-delà, arrêt forcé.
Solution : pas de gros calcul en Edge Function. Validation, proxy, calcul léger — le reste sur serveur central ou Worker dédié.
Piège 3 : mauvaise connexion base de données
En edge, une connexion Postgres longue par nœud sature le pool rapidement.
Utilisez le Pooler Supabase ou des connexions courtes libérées immédiatement. SUPABASE_DB_URL pointe vers le Pooler :
import { Pool } from "https://deno.land/x/[email protected]/mod.ts"
const pool = new Pool(Deno.env.get("SUPABASE_DB_URL")!, 10)
Deno.serve(async (req) => {
const client = await pool.connect()
try {
const result = await client.queryArray("SELECT * FROM users LIMIT 10")
return new Response(JSON.stringify(result.rows))
} finally {
client.release() // N'oubliez pas de libérer !
}
})
Piège 4 : JWT non configuré
En local, --no-verify-jwt pour déboguer. Déploiement sans réactiver la validation → n’importe qui peut appeler la fonction.
Configuration dans config.toml :
[functions.hello-world]
verify_jwt = true
Ou au déploiement :
supabase functions deploy hello-world --verify-jwt
Quelques astuces utiles
- Hono à la place de Deno.serve natif
Hono est un framework web ultra-léger pour le edge : routes, middleware, 13 KB seulement. Bien plus adapté qu’Express :
import { Hono } from "jsr:@hono/hono"
import { cors } from "jsr:@hono/hono/cors"
const app = new Hono()
app.use("*", cors())
app.get("/health", (c) => c.json({ status: "ok" }))
app.post("/echo", async (c) => {
const body = await c.req.json()
return c.json({ echo: body })
})
Deno.serve(app.fetch)
- Gestion des variables d’environnement
Deux runtimes : Main Runtime (contrôlé par Supabase) et User Runtime (votre code). Permissions différentes :
SUPABASE_URL,SUPABASE_ANON_KEY,SUPABASE_SERVICE_ROLE_KEYinjectées automatiquement- Variables personnalisées via Dashboard ou CLI :
supabase secrets set MY_VAR=value
- Import Map pour réduire la résolution
Beaucoup de modules externes ? Pré-définissez-les dans un Import Map :
// deno.json ou import_map.json
{
"imports": {
"hono": "jsr:@hono/hono",
"supabase-js": "jsr:@supabase/supabase-js@2"
}
}
Puis importez par nom court :
import { Hono } from "hono"
import { createClient } from "supabase-js"
Conclusion
En une phrase : Supabase Edge Functions pousse votre code au nœud le plus proche de l’utilisateur, sur le runtime Deno sécurisé, cold start 120 ms, distribution mondiale automatique.
Si vous utilisez déjà Supabase — Auth, Database ou Storage — Edge Functions est la suite naturelle. Pas de configuration connexion base, pas de Auth séparé, tout s’emboîte. Crainte du lock-in ? Deno est open source, Edge Runtime auto-hébergeable. Vous gardez une porte de sortie.
Prochaine étape : ouvrez le Dashboard Supabase, suivez le Quickstart. En 10 minutes, votre première Edge Function tourne sur le réseau edge mondial.
Autres articles de la série :
- Supabase pour débuter : PostgreSQL + Auth + Storage en un seul backend — vue d’ensemble Supabase
- Supabase Auth en pratique : vérification e-mail, OAuth et gestion de session — Auth en conditions réelles
- Supabase Auth avancé : OAuth, SSO et contrôle des permissions — configuration avancée
Intéressé par Cloudflare Workers ? Consultez aussi le guide des Workers KV. Chaque plateforme a ses forces — choisissez celle qui vous convient.
Déployer votre première Supabase Edge Function
Créer, tester et déployer une Edge Function sur le réseau edge mondial, de zéro
⏱️ Estimated time: 10 min
- 1
Step 1: Installer Supabase CLI
Installez Supabase CLI globalement :
```bash
npm install -g supabase
```
Puis vérifiez l'installation avec `supabase --version`. - 2
Step 2: Initialiser le projet
Dans le répertoire du projet, lancez l'initialisation :
```bash
supabase init
```
Cela crée le dossier `supabase` et le fichier de configuration `config.toml`. - 3
Step 3: Créer une Edge Function
Créez une nouvelle Edge Function via la CLI :
```bash
supabase functions new hello-world
```
La fonction générée se trouve dans `supabase/functions/hello-world/index.ts` et renvoie une réponse JSON par défaut. - 4
Step 4: Test local
Démarrez le serveur de développement local :
```bash
supabase functions serve --no-verify-jwt
```
Port par défaut 54321. Testez avec curl ou Postman :
```bash
curl -X POST http://localhost:54321/functions/v1/hello-world \
-H "Content-Type: application/json" \
-d '{"name":"Easton"}'
``` - 5
Step 5: Déployer sur le réseau edge mondial
Connectez-vous, liez le projet, puis déployez :
```bash
supabase login
supabase link --project-ref <your-project-id>
supabase functions deploy hello-world
```
Une fois déployé, consultez l'URL de la fonction et les logs dans le Dashboard. - 6
Step 6: Test d'appel
Appelez la fonction avec son URL et un token d'authentification :
```bash
curl -X POST https://<project-id>.supabase.co/functions/v1/hello-world \
-H "Authorization: Bearer <anon-key>" \
-H "Content-Type: application/json" \
-d '{"name":"World"}'
```
En production, activez la validation JWT : `supabase functions deploy hello-world --verify-jwt`
FAQ
Quelle est la différence entre Supabase Edge Functions et AWS Lambda ?
Peut-on utiliser des packages npm dans Edge Functions ?
Y a-t-il une limite de temps d'exécution pour Edge Functions ?
Comment se connecter à Postgres depuis une Edge Function ?
• Variable d'environnement `SUPABASE_DB_URL` (pointe automatiquement vers le Pooler)
• Package `postgres` pour créer un pool
• Libérer la connexion après chaque requête (`client.release()`)
Évitez les connexions longues : avec de nombreux nœuds edge, le pool sature rapidement.
Comment choisir entre Supabase Edge Functions et Cloudflare Workers ?
• Stack Supabase complète → Edge Functions (intégration profonde, développement rapide)
• Edge pur sans backend → Cloudflare Workers (cold start ~30 ms, plus rapide)
• Crainte du lock-in → Edge Functions (Deno open source, auto-hébergeable)
• Postgres en edge → Edge Functions (intégration native)
En pratique, vous pouvez combiner : Cloudflare Workers pour proxy et cache frontend, Edge Functions pour Auth et logique base de données.
Comment configurer la validation JWT pour protéger une Edge Function ?
• Fichier de config : ajoutez `[functions.hello-world] verify_jwt = true` dans `config.toml`
• Ligne de commande : ajoutez `--verify-jwt` au déploiement
En local, utilisez `--no-verify-jwt` pour les tests ; en production, activez impérativement la validation. Sans JWT, n'importe qui peut appeler votre fonction.
12 min de lecture · Publié le: 3 mai 2026 · Mis à jour le: 27 juil. 2026
Supabase en pratique
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Supabase Auth : OAuth, SSO et contrôle des accès en profondeur
Configuration avancée de Supabase Auth : intégration OAuth multi-fournisseurs, authentification SAML SSO entreprise, isolation multi-tenant avec RLS — schéma complet du consumer au SaaS B2B.
Partie 9 sur 10
Suivant
C’est le dernier article publié dans cette série pour le moment.



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire