Pourquoi Supabase Edge Functions change la donne pour vos API REST
Chez Otomy, on accompagne des PME françaises et algériennes dans la création de produits digitaux performants. Et un constat revient sans cesse : les fondateurs perdent des semaines à mettre en place une infrastructure backend alors qu'ils pourraient déjà valider leur produit sur le marché.
Supabase Edge Functions, basées sur Deno Deploy, permettent d'écrire des fonctions serverless en TypeScript, déployées instantanément sur un CDN mondial. Combinées à la base de données PostgreSQL de Supabase, à l'authentification intégrée et au stockage, elles forment un backend complet en quelques heures.
Voici comment nous construisons une API REST complète en 48 heures — pas un POC bancal, mais une API prête pour la production.
Heures 0-4 : Architecture et modélisation des données
Avant d'écrire la moindre ligne de code, on pose les fondations.
Définir les ressources de l'API
Prenons un cas concret : une API de gestion de commandes pour un e-commerce algérien.
Ressources identifiées :
/orders— CRUD complet/products— lecture seule pour le catalogue/customers— gestion des profils clients/webhooks— notifications vers n8n ou Make
Modéliser la base de données
Dans le SQL Editor de Supabase :
CREATE TABLE products (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
price NUMERIC(10,2) NOT NULL,
stock INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE orders (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
customer_id UUID REFERENCES auth.users(id),
status TEXT DEFAULT 'pending' CHECK (status IN ('pending','confirmed','shipped','delivered')),
total NUMERIC(10,2) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE order_items (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
product_id UUID REFERENCES products(id),
quantity INTEGER NOT NULL,
unit_price NUMERIC(10,2) NOT NULL
);
Astuce Otomy : Activez immédiatement les Row Level Security (RLS) policies. C'est non négociable en production.
Heures 4-16 : Développement des Edge Functions
Initialiser le projet
supabase init
supabase functions new orders-api
Structure d'une Edge Function RESTful
Voici le pattern que nous utilisons systématiquement pour gérer plusieurs méthodes HTTP dans une seule fonction :
// supabase/functions/orders-api/index.ts
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
};
serve(async (req) => {
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
);
const url = new URL(req.url);
const id = url.searchParams.get("id");
try {
switch (req.method) {
case "GET": {
const query = id
? supabase.from("orders").select("*, order_items(*)").eq("id", id).single()
: supabase.from("orders").select("*, order_items(*)").order("created_at", { ascending: false });
const { data, error } = await query;
if (error) throw error;
return new Response(JSON.stringify(data), {
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
case "POST": {
const body = await req.json();
const { data, error } = await supabase.from("orders").insert(body).select().single();
if (error) throw error;
return new Response(JSON.stringify(data), {
status: 201,
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
case "PATCH": {
if (!id) throw new Error("ID requis pour la mise à jour");
const body = await req.json();
const { data, error } = await supabase.from("orders").update(body).eq("id", id).select().single();
if (error) throw error;
return new Response(JSON.stringify(data), {
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
default:
return new Response("Méthode non autorisée", { status: 405, headers: corsHeaders });
}
} catch (err) {
return new Response(JSON.stringify({ error: err.message }), {
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
});
Validation des données
Utilisez Zod pour valider les entrées :
import { z } from "https://deno.land/x/zod@v3.22.4/mod.ts";
const OrderSchema = z.object({
customer_id: z.string().uuid(),
total: z.number().positive(),
items: z.array(z.object({
product_id: z.string().uuid(),
quantity: z.number().int().positive(),
unit_price: z.number().positive(),
})).min(1),
});
Heures 16-30 : Authentification, sécurité et intégrations
Sécuriser l'API avec JWT
Supabase gère l'authentification nativement. Extrayez le token JWT de chaque requête :
const authHeader = req.headers.get("Authorization");
const { data: { user }, error } = await supabase.auth.getUser(
authHeader?.replace("Bearer ", "")
);
if (!user) return new Response("Non autorisé", { status: 401, headers: corsHeaders });
Connecter n8n ou Make pour l'automatisation
Après la création d'une commande, déclenchez un workflow via webhook :
await fetch(Deno.env.get("N8N_WEBHOOK_URL")!, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ event: "order.created", data: newOrder }),
});
Ce webhook peut déclencher dans n8n : envoi d'email de confirmation, notification Slack, mise à jour du stock, ou sync avec un ERP.
Rate limiting basique
Stockez les compteurs dans Supabase KV ou une table dédiée pour limiter les abus.
Heures 30-42 : Tests et documentation
Tests automatisés
deno test --allow-net --allow-env supabase/functions/tests/
Écrivez des tests pour chaque endpoint. Utilisez Claude AI pour générer rapidement les cas limites à partir de votre schéma Zod.
Documentation avec OpenAPI
Générez une spec OpenAPI 3.0 et hébergez-la sur votre frontend Vercel ou Netlify. Les consommateurs de votre API vous remercieront.
Heures 42-48 : Déploiement et monitoring
Déployer en production
supabase functions deploy orders-api --project-ref votre-ref-projet
C'est tout. Votre API REST est live sur le edge, avec une latence inférieure à 50ms dans la plupart des régions.
Monitoring
- Supabase Dashboard : logs en temps réel des Edge Functions
- Logflare : intégré nativement pour l'analyse des logs
- Uptime Robot ou Better Stack : monitoring de disponibilité
Checklist finale avant mise en production
- ✅ RLS activé sur toutes les tables
- ✅ Validation Zod sur tous les inputs
- ✅ Authentification JWT vérifiée
- ✅ CORS configuré (remplacer
*par vos domaines) - ✅ Variables d'environnement en secrets Supabase
- ✅ Tests automatisés passants
- ✅ Webhooks n8n/Make opérationnels
- ✅ Documentation OpenAPI publiée
Ce que vous obtenez en 48 heures
| Composant | Outil |
|---|---|
| Base de données | Supabase PostgreSQL |
| API serverless | Supabase Edge Functions (Deno) |
| Authentification | Supabase Auth (JWT) |
| Automatisation | n8n / Make via webhooks |
| Hébergement frontend | Vercel / Netlify |
| Monitoring | Logflare + Better Stack |
Le résultat : une API REST complète, sécurisée, scalable, déployée mondialement — sans gérer un seul serveur.
Chez Otomy, c'est exactement cette approche que nous appliquons pour les PME qui veulent lancer un produit digital rapidement, que ce soit en France ou en Algérie. La vitesse d'exécution n'est pas l'ennemie de la qualité — à condition de choisir les bons outils.