L’essentiel en 30 secondes
- Les Edge Functions sont des fonctions TypeScript côté serveur sur un runtime compatible Deno : new, serve pour tester en local, deploy pour publier.
- Le modèle actuel utilise withSupabase (npm:@supabase/server), qui vérifie l'appelant selon un mode (user, secret, publishable, none) et gère CORS.
- Les secrets se posent avec supabase secrets set, sans redéploiement ; les noms commençant par SUPABASE_ sont réservés.
- Limites principales : 256 Mo de mémoire, 2 s de CPU par requête, 150 s (Free) ou 400 s (payant) de durée de worker ; 500 000 appels inclus en Free.
Les Edge Functions de Supabase sont des fonctions TypeScript exécutées côté serveur, sur un runtime compatible Deno distribué au plus près des utilisateurs. Elles servent aux webhooks (Stripe, GitHub), aux e-mails transactionnels, aux appels à des API d'IA et à toute logique qui exige une clé secrète1. Le cycle tient en trois commandes de la CLI : supabase functions new, supabase functions serve pour tester en local, supabase functions deploy pour publier2.
Pour la place des Edge Functions dans l'architecture Supabase, voir notre vue d'ensemble de Supabase.
Comment créer, tester et déployer une fonction ?
Le test local demande Docker (ou un runtime compatible) et une stack locale démarrée2.
supabase init # si le projet n'est pas encore initialisé
supabase functions new hello-world # crée supabase/functions/hello-world/index.ts
supabase start # stack locale (Docker)
supabase functions serve hello-world
# → http://localhost:54321/functions/v1/hello-world, rechargement à chaud
supabase login
supabase link --project-ref <project_ref>
supabase functions deploy hello-world # ou sans nom pour tout déployerSans Docker, deploy bascule automatiquement sur un empaquetage côté serveur (option --use-api). La fonction est ensuite disponible à https://<project_ref>.supabase.co/functions/v1/hello-world2. Pour le reste de la CLI, voir notre guide du développement local avec la CLI.
À quoi ressemble une fonction aujourd'hui ?
Le modèle généré par la CLI utilise désormais withSupabase, du paquet @supabase/server. Ce wrapper vérifie les identifiants de l'appelant selon un mode déclaré, gère CORS et les requêtes préliminaires OPTIONS, et fournit des clients Supabase prêts à l'emploi34 :
// supabase/functions/mes-commandes/index.ts
import { withSupabase } from 'npm:@supabase/server'
export default {
fetch: withSupabase({ auth: 'user' }, async (_req, ctx) => {
// ctx.supabase : client limité aux droits RLS de l'utilisateur
// ctx.supabaseAdmin : client qui contourne la RLS
// ctx.userClaims : identité issue du JWT (id, email, rôle)
const { data, error } = await ctx.supabase
.from('orders')
.select('id, total, created_at')
.order('created_at', { ascending: false })
if (error) return Response.json({ error: error.message }, { status: 400 })
return Response.json(data)
}),
}| Mode auth | Accepte | Usage |
|---|---|---|
| 'user' | Un JWT utilisateur valide dans Authorization | Appels depuis l'application, verify_jwt laissé à true |
| 'secret' | Une clé secret dans apikey | Cron, workers, pg_net, autre fonction |
| 'publishable' | Une clé publishable dans apikey | Appels publics identifiés par l'application |
| 'none' | Tout appelant | Webhooks signés, à vérifier dans la fonction |
Plusieurs modes peuvent être combinés (auth: ['user', 'secret']) ; ctx.authMode indique lequel a correspondu3.
Correction : l'ancienne version de cet article importait serve depuis https://deno.land/std@0.168.0/http/server.ts et supabase-js depuis esm.sh. La documentation actuelle utilise export default { fetch } ou Deno.serve, et les imports npm:45. Si vous n'utilisez pas withSupabase, importez les en-têtes CORS depuis npm:@supabase/supabase-js@^2/cors (supabase-js 2.95.0 et plus) plutôt que de les recopier à la main4.
Quelles variables d'environnement sont disponibles ?
Chaque fonction reçoit d'office5 :
SUPABASE_URLetSUPABASE_DB_URL(connexion directe à Postgres) ;SUPABASE_PUBLISHABLE_KEYSetSUPABASE_SECRET_KEYS, deux dictionnaires JSON de clés nommées ;SUPABASE_JWKS, pour vérifier les JWT des utilisateurs ;- les anciennes
SUPABASE_ANON_KEYetSUPABASE_SERVICE_ROLE_KEY, qui correspondent à des clés dépréciées d'ici fin 20266.
import { createClient } from 'npm:@supabase/supabase-js@2'
const secretKeys = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
const supabaseAdmin = createClient(Deno.env.get('SUPABASE_URL')!, secretKeys['default'])Comment gérer les secrets ?
En local, les fonctions lisent supabase/functions/.env (à ajouter au .gitignore). En production5 :
supabase secrets set STRIPE_SECRET_KEY=sk_live_...
supabase secrets set --env-file .env # tout un fichier
supabase secrets listLes secrets sont disponibles immédiatement, sans redéploiement. Un nom de secret ne peut pas commencer par SUPABASE_, préfixe réservé ; un projet accepte 100 secrets au maximum57. Créer ou supprimer un secret de production exige le rôle Owner ou Administrator5.
Comment recevoir un webhook Stripe ?
Un fournisseur externe n'envoie pas d'identifiants Supabase : on désactive verify_jwt pour cette fonction, on utilise auth: 'none' et on vérifie la signature du fournisseur dans le code. Sous Deno, la vérification Stripe doit passer par la version asynchrone et le SubtleCryptoProvider3.
# supabase/config.toml
[functions.stripe-webhook]
verify_jwt = falseimport { withSupabase } from 'npm:@supabase/server'
import Stripe from 'npm:stripe'
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY')!)
const cryptoProvider = Stripe.createSubtleCryptoProvider()
export default {
fetch: withSupabase({ auth: 'none' }, async (req, ctx) => {
const signature = req.headers.get('stripe-signature') ?? ''
const body = await req.text()
let event: Stripe.Event
try {
event = await stripe.webhooks.constructEventAsync(
body, signature, Deno.env.get('STRIPE_WEBHOOK_SECRET')!, undefined, cryptoProvider
)
} catch (err) {
console.error('Signature Stripe invalide :', err)
return new Response('bad signature', { status: 400 })
}
if (event.type === 'checkout.session.completed') {
// ctx.supabaseAdmin : mise à jour de la commande, contourne la RLS
}
return Response.json({ received: true })
}),
}auth: 'none' désactive toute vérification : la fonction est entièrement responsable d'authentifier l'appelant, ici par la signature3.
Comment appeler une fonction depuis le client ?
// Avec supabase-js : le JWT de l'utilisateur connecté est transmis automatiquement
const { data, error } = await supabase.functions.invoke('mes-commandes', {
body: { limit: 10 },
})
// Avec fetch
const res = await fetch('https://<project_ref>.supabase.co/functions/v1/mes-commandes', {
method: 'POST',
headers: {
apikey: 'sb_publishable_...',
Authorization: `Bearer ${session.access_token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ limit: 10 }),
})Les clés publishable et secret se passent dans l'en-tête apikey, pas en Authorization: Bearer : ce ne sont pas des JWT6.
Quelles limites et quel coût ?
| Limite | Valeur |
|---|---|
| Mémoire | 256 Mo |
| Durée de vie d'un worker (horloge) | 150 s en Free, 400 s sur les plans payants |
| Temps CPU par requête | 2 s (hors attente d'entrées-sorties) |
| Délai sans réponse | 150 s, puis erreur 504 |
| Taille d'une fonction | 20 Mo empaquetée par la CLI, 5 Mo côté serveur |
| Nombre de fonctions | 100 (Free), 1 000 (Pro), 2 000 (Team) |
| Réseau | Ports sortants 25 et 587 bloqués |
Autres restrictions : pas de Web Workers, pas de bibliothèques Node multithread (sharp, libvips), et le HTML n'est servi tel quel qu'avec un domaine personnalisé7. Côté prix, 500 000 appels par mois sont inclus en Free, 2 millions en Pro et Team, puis 2 $ par million8. Pour les traitements longs, Supabase oriente vers les tâches en arrière-plan1.
Pour concevoir une intégration (paiement, IA, CRM) sur Edge Functions, voir notre offre de développement d'intégrations sur mesure ; pour sécuriser les données que ces fonctions manipulent, la sécurité des données avec la RLS.
Sources
- Edge Functions (documentation Supabase)
- Getting Started with Edge Functions (documentation Supabase)
- Securing Edge Functions (documentation Supabase)
- CORS support for invoking from the browser (documentation Supabase)
- Environment variables (documentation Supabase)
- API keys (documentation Supabase)
- Edge Functions Limits (documentation Supabase)
- Edge Functions Pricing (documentation Supabase)






Commentaires
Chaque commentaire est relu avant publication, en général sous 24 h ouvrées. Les liens promotionnels ne sont pas publiés.
Aucun commentaire pour l’instant. Une question sur l’article ? Posez-la ci-dessous.