Introduction
Deno Deploy est la plateforme serverless d'edge computing de Deno, lancée pour simplifier les déploiements globaux sans configuration serveur. En 2026, elle excelle par sa vitesse (cold starts <1ms), son intégration native avec le runtime Deno sécurisé, et son modèle gratuit pour les petits projets. Contrairement à Vercel ou Cloudflare Workers, Deno Deploy utilise directement TypeScript/Deno sans bundling, avec support KV, D1 et queues.
Pourquoi l'utiliser ? Pour des APIs REST scalables distribuées sur 40+ edges mondiaux, sans frais initiaux. Imaginez une API qui répond en 10ms depuis Paris ou Tokyo. Ce tutoriel beginner vous emmène des bases (serveur HTTP simple) à l'avancé (routes + KV persistant), avec code 100% fonctionnel. À la fin, votre app sera live en 10 min, bookmark-worthy pour tout dev Deno.
Prérequis
- Deno 2.0+ installé (exécutez
deno --versionpour vérifier) - Compte gratuit sur deno.com et projet Deploy créé (dashboard.deno.com > Deployments > New Project)
- Token API : dashboard > Settings > API Tokens > Create Token (nommez-le "deploy-token")
- Git installé (optionnel, pour CI/CD)
- Éditeur comme VS Code avec extension Deno
Installer deployctl
curl -fsSL https://deno.land/x/install/install.sh | sh
# Redémarrer le terminal ou source le profil
# Installer deployctl (CLI officiel Deno Deploy)
denop install -A -f --unstable https://deno.land/x/deploy@0.8.6/deployctl.ts
# Vérifier
deployctl --versionCe script installe Deno si absent, puis deployctl pour gérer les déploiements. L'option --unstable est requise pour les features edge actuelles. Évitez les versions globales npm pour rester dans l'écosystème Deno pur ; testez toujours avec --version pour confirmer.
Préparer le projet local
Créez un dossier vide mon-app-deno et naviguez dedans. Copiez les codes suivants. Deno Deploy déploie directement depuis un .ts sans build, mais une config deno.json optimise les imports et locks les versions pour reproductibilité.
Configurer deno.json
{
"name": "mon-app-deno-deploy",
"version": "0.1.0",
"lock": true,
"tasks": {
"start": "deno run --allow-net --allow-env main.ts",
"deploy": "deployctl deploy --project=monprojet main.ts"
},
"imports": {
"$std/http/": "https://deno.land/std@0.224.0/http/"
}
}Ce fichier lock les dépendances std pour éviter les breaks de version sur Deploy. Les tasks facilitent deno task start local et deploy. Remplacez monprojet par votre nom de projet dashboard ; --lock true garantit des déploiements identiques.
Serveur HTTP de base
import { serve } from "https://deno.land/std@0.224.0/http/server.ts";
serve((req: Request) => {
const url = new URL(req.url);
if (url.pathname === "/") {
return new Response(JSON.stringify({ message: "Hello Deno Deploy!", timestamp: new Date().toISOString() }), {
headers: { "Content-Type": "application/json" },
});
}
return new Response("Not Found", { status: 404 });
}, { port: 8000 });
console.log("Serveur local sur http://localhost:8000");Ce handler minimal utilise serve de std pour un serveur HTTP. Il répond JSON sur / avec timestamp live. Testez localement avec deno task start (autorise --allow-net). Piège : oubliez les headers JSON, les clients fetch échouent ; port 8000 pour éviter conflits.
Tester localement
Exécutez deno task start (ou deno run --allow-net main.ts). Ouvrez http://localhost:8000. Vous verrez {"message":"Hello Deno Deploy!","timestamp":"2026-..."}. Arrêtez avec Ctrl+C. Cette étape valide le code avant deploy, économisant des itérations coûteuses.
Ajouter des routes API
import { serve } from "https://deno.land/std@0.224.0/http/server.ts";
serve((req: Request) => {
const url = new URL(req.url);
const pathname = url.pathname;
if (pathname === "/api/users") {
if (req.method === "GET") {
return new Response(JSON.stringify([
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]), {
headers: { "Content-Type": "application/json" },
});
}
if (req.method === "POST") {
const body = await req.json();
return new Response(JSON.stringify({ message: "User créé", user: body }), {
status: 201,
headers: { "Content-Type": "application/json" },
});
}
}
if (pathname === "/") {
return new Response(JSON.stringify({ message: "API prête !" }), {
headers: { "Content-Type": "application/json" },
});
}
return new Response("Not Found", { status: 404 });
});Routes /api/users GET (liste mock) et POST (écho body). Parsing req.json() pour inputs. Analogie : comme Express mais natif Deno, zéro deps. Piège : gérez req.method strictement ; sans await sur POST, body vide crash.
Intégrer KV pour persistance
import { serve } from "https://deno.land/std@0.224.0/http/server.ts";
// KV sur Deno Deploy (créé auto ou via dashboard)
const kv = await Deno.openKv();
serve(async (req: Request) => {
const url = new URL(req.url);
const pathname = url.pathname;
if (pathname === "/api/users" && req.method === "GET") {
const users: Record<string, any>[] = [];
for await (const entry of kv.list({ prefix: ["users"] })) {
users.push(entry.value);
}
return new Response(JSON.stringify(users), {
headers: { "Content-Type": "application/json" },
});
}
if (pathname === "/api/users" && req.method === "POST") {
const body = await req.json();
const id = crypto.randomUUID();
await kv.set(["users", id], { id, ...body });
return new Response(JSON.stringify({ message: "User créé", id }), {
status: 201,
headers: { "Content-Type": "application/json" },
});
}
return new Response(JSON.stringify({ error: "Not Found" }), { status: 404 });
});Deno KV (global, persistant, edge) stocke users. Deno.openKv() auto sur Deploy. GET liste via iterator, POST UUID + set. Analogie : Redis mais serverless gratuit. Piège : async handler obligatoire pour KV ; sans await kv.set, données perdues.
Déployer sur Deno Deploy
# Définir les vars env (ajoutez à .env ou shell)
export DENO_DEPLOY_TOKEN="votre_token_dashboard"
export DENO_PROJECT_NAME="monprojet"
# Dry-run pour valider
deployctl deploy --project=$DENO_PROJECT_NAME main.ts --dry-run
# Déployer (exclut node_modules, .git)
deployctl deploy --project=$DENO_PROJECT_NAME main.ts --exclude="*.md,node_modules"
# URL live : https://monprojet.deno.dev
# Logs
deployctl logs --project=$DENO_PROJECT_NAME --watchdeployctl push vers edge en secondes. --dry-run valide sans deploy. Token sécurisé en env. URL auto : projet.deno.dev. Piège : token périmé = 401 ; --exclude évite upload inutiles, réduisant bundle de 90%.
Bonnes pratiques
- Locks et versions : Toujours
deno.jsonaveclock: truepour déploiements stables. - Permissions minimales : Local
--allow-net --allow-env, Deploy auto-gère. - CORS headers : Ajoutez
Access-Control-Allow-Origin: *pour APIs frontend. - Monitoring : Utilisez
deployctl logs --watchet dashboard metrics. - CI/CD : Intégrez GitHub Actions avec
deployctlpour auto-deploys.
Erreurs courantes à éviter
- Token invalide : 401 sur deploy → recréer token avec scopes Deploy.
- Imports cassés : Versions std changeantes → lock via deno.json.
- Cold starts lents : Évitez heavy deps ; std est optimisé edge.
- KV non-async : Oubli
await→ données non persistées, handler sync crash.
Pour aller plus loin
Maîtrisez Deno Deploy avancé : queues, D1 SQL, custom domains. Consultez la doc officielle Deno Deploy. Pour une formation experte, découvrez nos formations Learni sur Deno et serverless. Prochain niveau : APIs full-stack avec Fresh + Deploy.