Aller au contenu principal

Cloudflare Workers : API locale, stockage et préparation à la production

Cloudflare Workers reçoit des requêtes HTTP, exécute du code et renvoie des réponses. Il convient aux petites API, au transfert de requêtes, aux contrôles d'autorisation et aux fonctions dynamiques d'un site statique. Vous écrivez la logique de traitement ; Cloudflare exploite l'environnement d'exécution. Il n'est pas nécessaire de configurer d'abord un serveur Linux.

Ce guide commence par une API TypeScript locale : vérifier son état, envoyer un nom et recevoir une salutation. Une requête facultative sur une base locale vient ensuite, suivie des choix de stockage, des domaines, de la sécurité et des coûts. L'exemple de base ne demande ni connexion à un compte, ni déploiement, ni ressource cloud, ni secret ; la création du projet télécharge des dépendances de développement. Il suffit de savoir modifier des fichiers, utiliser un terminal et lire du JavaScript simple.

1. Comprendre où s'exécute le code

Workers utilise des isolates V8 : des environnements JavaScript séparés au sein d'un même moteur d'exécution, plutôt qu'une machine virtuelle par application. workerd est le moteur de Workers ; Wrangler l'utilise aussi pour le développement local. À l'arrivée d'une requête HTTP, la plateforme appelle votre gestionnaire fetch exporté, qui renvoie une réponse. Voir le modèle d'exécution et la documentation du développement local.

Les entrées et la sortie du gestionnaire ont des rôles distincts :

  • request est un objet Web Request, contenant l'URL, la méthode, les en-têtes et le corps.
  • L'objet Web Response renvoyé contient un code d'état, des en-têtes et un corps.
  • env expose les valeurs de configuration et les liaisons, appelées bindings. Une liaison est une interface vers une ressource fournie par la plateforme, par exemple env.DB, et non une simple chaîne contenant l'adresse d'une base.
  • Le paramètre facultatif ctx fournit des outils liés au cycle de vie de la requête, notamment pour un bref travail après la réponse. Il ne transforme pas une tâche en processus permanent en arrière-plan.
  • Le nom du gestionnaire, fetch, désigne le traitement des requêtes entrantes. Appeler la fonction globale fetch(url) à l'intérieur envoie une autre requête HTTP.

Ce modèle ne demande pas à l'application de gérer un port avec listen(). Les variables définies au niveau du module peuvent être réutilisées entre requêtes ou disparaître lorsque l'isolate est évincé. N'y conservez pas l'utilisateur courant, des commandes ou un compteur qui doit persister de façon fiable. Même lorsque certaines API de fichiers sont disponibles, ne les traitez pas comme le disque persistant d'un serveur.

Date de compatibilité et Node.js

compatibility_date choisit une base de comportement du moteur. Ce n'est ni une version de Node ni une date de déploiement. Pour un nouveau projet, suivez la recommandation officielle d'utiliser la date courante ; lors d'une mise à jour, examinez les changements et relancez les tests. Cette date ne fixe pas les dépendances npm : elles nécessitent toujours un fichier de verrouillage. Dates de compatibilité

Consultée le 2026-09-12, la documentation de compatibilité Node.js indique qu'à partir de la date de compatibilité 2026-08-04, le comportement de nodejs_compat et de nodejs_compat_v2 est activé par défaut. Il est inutile de répéter ces indicateurs dans une nouvelle configuration. Entre 2024-09-23 et 2026-08-03, l'activation explicite de nodejs_compat est nécessaire. La prise en charge reste limitée aux API Node documentées et aux implémentations complémentaires ; certains modules sont des substituts importables dont les méthodes lèvent une erreur. Pouvoir installer un paquet npm ne prouve pas qu'il fonctionne. Évaluez séparément les extensions natives, les services du système et les hypothèses de processus permanent. L'API ci-dessous utilise uniquement des API Web, sans dépendre de la compatibilité Node.

2. Workers, hébergement statique, conteneurs ou VPS ?

Le tableau propose des points de départ architecturaux, pas un classement par coût ou latence. La page officielle de Pages recommande actuellement Workers pour les nouveaux projets ; cela n'impose pas de migrer les sites Pages existants.

BesoinPremier choix à examinerPoints à prendre en compte
Petite API HTTP, transfert, autorisation à l'entrée des requêtesWorkersCompatibilité du moteur, budgets CPU et mémoire, stockage en aval
HTML, CSS, images et petite API associéeWorkers Static AssetsRoutage des fichiers et invocation du Worker ; ne pas supposer que chaque fichier passe par le code d'autorisation
Site Pages existant avec un processus de construction fiableConserver Pages ; envisager une migration pour un besoin concretChoisir Workers pour un nouveau projet n'oblige pas à migrer l'existant
Image de conteneur existante ou service Web conçu pour un conteneurCloud RunDémarrage, configuration du service, dépendances et mise à l'échelle ; l'unité d'exécution n'est pas un isolate V8
Contrôle complet du système, démons personnalisés et logiciels serveurVPSMises à jour, réseau, gestion des processus, sauvegardes et restauration

Pour valider un formulaire et renvoyer du JSON, commencez par évaluer un Worker. Pour un service conteneurisé avec des dépendances natives, Cloud Run peut être plus direct. L'emplacement d'exécution et celui de la base influencent tous deux la latence ; Workers n'est pas systématiquement plus rapide ou moins cher qu'un VPS.

3. Créer un projet uniquement local

Préparer les outils

Installez une version de Node.js en phase Current, Active LTS ou Maintenance LTS, npm et curl. Suivez la politique d'installation de Wrangler plutôt qu'un ancien numéro minimal de Node figurant dans un guide de démarrage. Node exécute les outils de développement ; cela ne transforme pas le Worker déployé en serveur Node.

Dans un nouveau répertoire de travail, suivez le démarrage officiel avec C3 :

npm create cloudflare@latest -- workers-local-api
cd workers-local-api

C3 génère le projet ; Wrangler est l'outil en ligne de commande pour développer, configurer et publier des Workers. Choisissez un exemple Worker minimal et TypeScript, puis refusez le déploiement. Le libellé des questions peut changer. Si une connexion ou une autorisation est demandée, arrêtez-vous : elle ne fait pas partie de cet exercice local. Conservez les dépendances compatibles, le fichier de verrouillage et la configuration TypeScript générés par C3, sans effectuer aussitôt une deuxième mise à jour de Wrangler.

Configuration

Remplacez wrangler.jsonc par le contenu suivant. JSONC accepte les commentaires et constitue le format de configuration recommandé. APP_ENV est une valeur de configuration ordinaire. Configuration Wrangler

{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "workers-local-api",
"main": "src/index.ts",
"compatibility_date": "2026-09-12",
"vars": {
"APP_ENV": "local"
}
}

La date définit le comportement retenu pour ce tutoriel ; ce n'est pas un numéro de version Wrangler. Si l'outil local signale qu'il ne la prend pas en charge, n'ignorez pas l'avertissement et ne considérez pas cette configuration comme testée. Vérifiez la version installée et ses consignes de mise à jour, puis ajustez délibérément l'outil ou la date et refaites les tests.

Gestionnaire complet des requêtes

Remplacez src/index.ts par le code suivant. Env et ExportedHandler proviennent des types Workers générés à l'étape suivante ; n'installez pas un autre ensemble de types d'exécution incompatible.

function json(value: unknown, status = 200, extra: HeadersInit = {}) {
const headers = new Headers(extra);
headers.set("content-type", "application/json; charset=utf-8");
headers.set("cache-control", "no-store");
return new Response(JSON.stringify(value), { status, headers });
}

function error(status: number, code: string, extra: HeadersInit = {}) {
return json({ error: code }, status, extra);
}

async function readSmallBody(request: Request): Promise<string | null> {
if (!request.body) return "";
const reader = request.body.getReader();
const chunks: Uint8Array[] = [];
let size = 0;
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
size += value.byteLength;
if (size > 4096) {
await reader.cancel();
return null;
}
chunks.push(value);
}
} finally {
reader.releaseLock();
}
const bytes = new Uint8Array(size);
let offset = 0;
for (const chunk of chunks) {
bytes.set(chunk, offset);
offset += chunk.byteLength;
}
return new TextDecoder().decode(bytes);
}

export default {
async fetch(request: Request, env: Env): Promise<Response> {
const path = new URL(request.url).pathname;
try {
if (path === "/health") {
if (request.method !== "GET") {
return error(405, "method_not_allowed", { Allow: "GET" });
}
return json({ ok: true, environment: env.APP_ENV });
}
if (path !== "/api/greet") return error(404, "not_found");
if (request.method !== "POST") {
return error(405, "method_not_allowed", { Allow: "POST" });
}
const type = request.headers.get("content-type")
?.split(";", 1)[0].trim().toLowerCase();
if (type !== "application/json") {
return error(415, "unsupported_media_type");
}
const text = await readSmallBody(request);
if (text === null) return error(413, "payload_too_large");
let payload: unknown;
try {
payload = JSON.parse(text);
} catch {
return error(400, "invalid_json");
}
if (typeof payload !== "object" || payload === null ||
Array.isArray(payload) || !("name" in payload) ||
typeof payload.name !== "string") {
return error(400, "invalid_name");
}
const name = payload.name.trim();
if (name.length < 1 || name.length > 80) {
return error(400, "invalid_name");
}
return json({ message: `Hello, ${name}!` });
} catch {
console.error("request_failed", { method: request.method });
return error(500, "internal_error");
}
},
} satisfies ExportedHandler<Env>;

L'interface accepte un objet JSON. Après suppression des espaces aux extrémités, name doit contenir 1–80 unités de code d'une chaîne JavaScript ; les propriétés supplémentaires sont ignorées. Une unité de code n'est pas un caractère visible : certains emoji en occupent deux. Le corps est limité à 4096 octets effectivement lus, sans faire confiance au Content-Length fourni par le client. Cela borne les données mises en mémoire, mais ne protège pas à lui seul contre les clients lents ou le trafic abusif.

Une mauvaise méthode sur un chemin connu renvoie 405 avec Allow ; un chemin inconnu renvoie 404. Les erreurs ne révèlent pas les détails des exceptions et toutes les réponses désactivent la mise en cache. L'exemple distingue strictement les méthodes : ni HEAD ni OPTIONS ne sont pris en charge implicitement, et aucun en-tête CORS permissif n'est ajouté. Il n'effectue aucune opération sensible. Le transformer en interface d'écriture anonyme dans une base ne le rendrait pas prêt pour la production.

Générer les types et démarrer

Wrangler génère les types à partir de la configuration, des liaisons, de la date de compatibilité et des indicateurs. Exécutez :

npx wrangler types
npx tsc --noEmit
npx wrangler dev --local

Vérifiez le tsconfig.json de C3 : compilerOptions.types doit inclure ./worker-configuration.d.ts, en conservant les autres entrées nécessaires. Si Env ou ExportedHandler reste introuvable, vérifiez ce réglage et le fichier généré au lieu de masquer le problème avec any. Régénérez les types après une modification de configuration. Guide TypeScript

L'adresse locale par défaut est http://localhost:8787 ; fiez-vous à celle affichée dans le terminal. Si le port est occupé, lancez npx wrangler dev --local --port 8788 et adaptez les URL ci-dessous.

Vérifier les réussites et les erreurs avec curl

Laissez le processus de développement actif. Dans un deuxième terminal, depuis le répertoire du projet, exécutez :

npx wrangler types --check
npx tsc --noEmit
curl -i http://localhost:8787/health
curl -i -X POST http://localhost:8787/api/greet \
-H 'Content-Type: application/json' --data '{"name":"Ada"}'
curl -i -X POST http://localhost:8787/api/greet \
-H 'Content-Type: application/json' --data '{"name":" "}'
curl -i -X POST http://localhost:8787/api/greet \
-H 'Content-Type: application/json' --data '{'
curl -i http://localhost:8787/api/greet
curl -i -X POST http://localhost:8787/api/greet --data 'name=Ada'
curl -i http://localhost:8787/missing
node -e 'process.stdout.write(JSON.stringify({name:"a".repeat(4097)}))' | \
curl -i -X POST http://localhost:8787/api/greet \
-H 'Content-Type: application/json' --data-binary @-

Le tableau donne les résultats que le code doit produire, à comparer à votre exécution locale. La seule vérification des types ne prouve pas le bon comportement HTTP.

Ordre des requêtesÉtatCorps et en-tête requis
État du service200{"ok":true,"environment":"local"}
Nom valide200{"message":"Hello, Ada!"}
Nom composé d'espaces400{"error":"invalid_name"}
JSON mal formé400{"error":"invalid_json"}
GET sur la salutation405{"error":"method_not_allowed"}, Allow: POST
Type de média de formulaire415{"error":"unsupported_media_type"}
Chemin inconnu404{"error":"not_found"}
Plus de 4096 octets413{"error":"payload_too_large"}

Si la connexion est refusée, vérifiez d'abord que Wrangler tourne toujours et que le port correspond. Une erreur 415 indique souvent un en-tête JSON manquant ; pour 400, examinez la syntaxe JSON et les champs. Toute erreur ne vient pas d'un problème d'autorisation sur la plateforme.

4. Un code local peut accéder à des ressources distantes

La documentation du développement local distingue l'emplacement du code de celui des ressources. Le développement local ordinaire utilise workerd, et les liaisons peuvent accéder à des ressources simulées localement. Avec remote: true, le code local peut utiliser une ressource réelle ; wrangler dev --remote téléverse le code pour l'exécuter à distance.

Ce tutoriel impose les liaisons locales avec --local et ne configure aucune ressource distante. Ce n'est pas un bac à sable réseau : un fetch() externe peut toujours appeler une vraie API, envoyer des données ou entraîner des frais. Les fonctions toujours distantes, comme Workers AI, sont exclues de l'exercice.

Placez la configuration ordinaire dans vars, pas les identifiants secrets. Si des secrets locaux deviennent nécessaires, utilisez .dev.vars ou .env à côté de la configuration et vérifiez que Git les ignore. Ce sont des fichiers locaux en clair. .dev.vars.<env> remplace le fichier de base .dev.vars, tandis que les fichiers de la famille .env fusionnent selon leur priorité : les règles de chargement diffèrent. Documentation des secrets

En particulier, npx wrangler secret put KEY crée une version et la déploie immédiatement. npx wrangler versions secret put KEY crée une version sans la déployer. Les deux modifient l'état du cloud ; aucune n'est une étape de configuration locale. Cet exemple n'a besoin d'aucun secret.

5. Choisir les liaisons selon les données

Les noms de liaison doivent être des identifiants JavaScript valides : DB dans la configuration devient env.DB dans le code. Une liaison donne accès à une ressource ; elle ne décide pas si l'utilisateur courant peut lire un enregistrement particulier. Configuration des liaisons

RessourceUsage adaptéErreur fréquente
KVConfiguration surtout lue, ou cache tolérant des valeurs anciennesCohérence à terme : la propagation entre emplacements peut prendre 60 secondes ou plus ; les résultats absents sont aussi mis en cache. Ni verrou ni compteur atomique fiable
D1Données relationnelles fondées sur SQLite, requêtes SQL et contraintesConcevoir tables et requêtes pour la base ; vérifier séparément les limites de capacité et de concurrence
R2Objets accessibles par clé : images, pièces jointes, sauvegardesLe stockage objet n'est ni une base relationnelle ni un système de fichiers partagé
Durable ObjectsSalons de discussion, coordination par entité et traitement avec stockage fortement cohérentEnvoyer le travail lié à la même identité d'objet ; cela ne sérialise pas automatiquement toute l'application
QueuesTravail asynchrone nécessitant des tentatives supplémentairesLivraison au moins une fois par défaut, donc doublons possibles ; ne pas supposer un traitement exactement une fois ou dans l'ordre
Service bindingsUn Worker appelle les méthodes ou le gestionnaire HTTP d'un autrePas besoin d'URL publique ; définir tout de même les droits des appelants et l'exposition publique du service cible

La « cohérence à terme » signifie qu'après une écriture, des lecteurs situés à différents endroits peuvent voir temporairement des valeurs différentes. Le cacheTtl de KV peut prolonger cette période. Un décrément fiable de stock soumis à des accès concurrents ne peut donc pas se résumer à « lire KV, soustraire un, réécrire ».

Un consommateur de file doit être idempotent : traiter plusieurs fois le même événement ne doit pas débiter deux fois ni créer des doublons métier. Attribuez un ID unique à l'événement et validez, dans une même transaction, l'effet en base et l'enregistrement de cet ID sous contrainte d'unicité. Pour un service de paiement externe, utilisez la clé d'idempotence qu'il prend en charge. Une séquence séparée « vérifier si déjà traité, puis agir » reste exposée à une concurrence entre traitements.

6. Facultatif : lire une note locale avec D1

Cette section s'adresse aux lecteurs qui disposent déjà de l'identité d'une base dédiée au tutoriel. Créer la base est une opération cloud ; cette section ne crée aucune ressource et n'emprunte pas de base de production. Sans ce prérequis, conservez l'API de salutation comme exemple fonctionnel. N'inventez pas d'UUID de base pour donner l'apparence d'une configuration complète.

Remplacez la configuration par cette variante complète et substituez l'ID réel de la base dédiée au texte indicatif. Elle n'est pas exécutable telle quelle. Les commandes avec --local utilisent une base locale distincte et n'initialisent pas les données distantes. Démarrage D1 et développement local

{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "workers-local-api",
"main": "src/index.ts",
"compatibility_date": "2026-09-12",
"vars": { "APP_ENV": "local" },
"d1_databases": [
{
"binding": "DB",
"database_name": "workers-tutorial-db",
"database_id": "REPLACE_WITH_DEDICATED_DATABASE_ID"
}
]
}

Créez schema.sql à la racine du projet :

CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL
);
INSERT OR IGNORE INTO notes (id, title) VALUES (1, 'Local D1 note');

Arrêtez le premier processus de développement, puis initialisez et interrogez la base localement :

npx wrangler d1 execute workers-tutorial-db --local --file=./schema.sql
npx wrangler d1 execute workers-tutorial-db --local --command='SELECT id, title FROM notes;'
npx wrangler types

La requête doit afficher l'ID 1 et le titre Local D1 note. Le type Env généré contient désormais DB. Dans le try externe du gestionnaire initial, avant if (path !== "/api/greet"), insérez :

if (path === "/api/note") {
if (request.method !== "GET") {
return error(405, "method_not_allowed", { Allow: "GET" });
}
const id = new URL(request.url).searchParams.get("id");
if (!id || !/^[1-9]\d*$/.test(id) || !Number.isSafeInteger(Number(id))) {
return error(400, "invalid_id");
}
const result = await env.DB
.prepare("SELECT id, title FROM notes WHERE id = ?")
.bind(Number(id))
.run();
return json({ notes: result.results });
}

Le ? SQL est un emplacement réservé à un paramètre. .bind() sépare les valeurs de la structure SQL, au lieu de concaténer l'entrée dans la requête. Cette route lit uniquement les données locales de démonstration ; ajoutez l'authentification et l'autorisation par enregistrement avant de l'utiliser pour des notes privées.

npx wrangler types --check
npx tsc --noEmit
npx wrangler dev --local

Vérifiez dans un deuxième terminal :

curl -i 'http://localhost:8787/api/note?id=1'
curl -i 'http://localhost:8787/api/note?id=2'
curl -i 'http://localhost:8787/api/note?id=bad'

Dans l'ordre, attendez 200 avec {"notes":[{"id":1,"title":"Local D1 note"}]}, 200 avec {"notes":[]}, puis 400 avec {"error":"invalid_id"}. no such table indique généralement que le schéma n'a pas été appliqué dans le même projet et au même emplacement d'état local. Vérifiez le nom de la base et --local ; ne passez pas à une exécution distante pour essayer. Les données locales persistent pour les prochaines séances mais ne sont pas téléversées automatiquement. Une réussite locale ne prouve pas qu'une migration de production a eu lieu.

7. Avant publication : vérifier routage et environnements séparément

Arrêtez-vous ici si vous souhaitez seulement faire l'exercice local. La suite explique le routage et les environnements, puis propose un déploiement cloud facultatif qui ouvre une session, expose une API publique et peut entraîner des frais. Ce déploiement minimal ne crée pas de base, ne téléverse pas de secret et ne modifie aucun domaine.

La documentation du routage distingue trois entrées :

EntréeUsage
workers.devSous-domaine fourni par Cloudflare pour commencer ; la documentation recommande une route ou un domaine personnalisé pour un service de production critique pour l'activité
Custom DomainLe Worker devient le serveur d'origine de l'application sur un domaine ou sous-domaine possédé dans une zone Cloudflare
RouteExécute le Worker pour le trafic correspondant dans une zone, souvent devant un serveur d'origine existant

Une zone est un espace DNS géré par Cloudflare ; le serveur d'origine fournit réellement le contenu de l'application. Avant de reprendre un nom d'hôte, examinez le trafic existant, le DNS et le comportement de repli. Ces entrées ne sont pas des adresses interchangeables. Si le Worker assure des contrôles de sécurité, laisser passer directement vers l'origine lors d'un dépassement de quota peut les contourner. Choisissez le comportement d'échec selon le risque pour les données. Limites et comportement en cas de dépassement

Configurez explicitement les variables et les ressources de préproduction, ou staging, et de production. Les vars et les liaisons Wrangler ne sont pas automatiquement héritées par les environnements nommés : un nom d'environnement n'isole pas une base. APP_ENV: local est une étiquette, pas un commutateur qui déplace les ressources. Configuration des environnements

Vous pouvez commencer par ajouter localement les variables de env.staging et, si nécessaire, une liaison D1 dédiée, puis vérifier avec npx wrangler dev --local --env staging. Avant chaque commande sur une ressource, confirmez le compte, l'environnement, l'ID de ressource et les options locales ou distantes. Ne reliez jamais la préproduction à la base de production sous prétexte que le code est identique.

Facultatif : publier un Worker réservé à l'exercice

Lisez la section tarifaire ci-dessous et vérifiez que votre compte autorise ce déploiement. Utilisez le gestionnaire de base de la section 3, sans la route D1 ajoutée à la section 6 ; si vous avez réalisé cette extension, rétablissez d'abord le src/index.ts complet de la section 3. Cet exemple public renvoie uniquement un état de santé et des salutations. Il ne conserve aucune donnée utilisateur et ne fournit aucune fonction métier privée.

Remplacez wrangler.jsonc par la configuration complète ci-dessous, en choisissant pour YOUR_UNUSED_WORKER_NAME un nom d'exercice encore inutilisé dans votre compte. Ne réutilisez pas le nom d'un Worker en service. Aucune base, route de domaine ou liaison secrète n'est configurée :

{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "YOUR_UNUSED_WORKER_NAME",
"main": "src/index.ts",
"compatibility_date": "2026-09-12",
"vars": { "APP_ENV": "local" },
"env": {
"tutorial": {
"workers_dev": true,
"vars": { "APP_ENV": "tutorial" }
}
}
}

Les règles des environnements nommés donnent à ce Worker le nom principal suivi de -tutorial. workers_dev fournit une entrée publique, pas un contrôle d'accès. Générez les types, vérifiez le code et essayez d'abord la compilation :

npx wrangler types
npx tsc --noEmit
npx wrangler deploy --env tutorial --dry-run

--dry-run compile sans publier sur les serveurs. Il ne vérifie ni les autorisations du compte ni le comportement distant, et ne garantit pas l'absence d'écritures locales. Une fois cette étape réussie, la connexion lance l'autorisation OAuth dans le navigateur. Confirmez le compte voulu, puis déployez :

npx wrangler login
npx wrangler deploy --env tutorial

Si votre identité a accès à plusieurs comptes, confirmez la destination dans les invites de la CLI. Utilisez l'URL HTTPS réellement affichée après le déploiement, sans deviner le sous-domaine. Remplacez l'adresse ci-dessous avant de la vérifier :

export WORKER_URL="https://YOUR_DEPLOYED_WORKER_HOST"
curl -i "$WORKER_URL/health"
curl -i -X POST "$WORKER_URL/api/greet" \
-H 'Content-Type: application/json' --data '{"name":"Ada"}'

Attendez HTTP 200 avec, respectivement, {"ok":true,"environment":"tutorial"} et {"message":"Hello, Ada!"}. L'étiquette tutorial aide à repérer une requête arrivée dans le mauvais environnement, sans remplacer la vérification de l'URL. Après une modification, refaites les vérifications locales avant la même commande de déploiement ciblée. Pour observer les requêtes réelles, utilisez npx wrangler tail --env tutorial ; cette commande consulte les journaux cloud, qui peuvent être échantillonnés lorsque le trafic est élevé. Ctrl-C arrête leur consultation, pas le Worker déployé.

8. Sécurité, journaux et restauration

Avant d'exposer de vraies fonctions

  • Identité et droits : validez une session ou un jeton, puis vérifiez si cet utilisateur peut effectuer cette opération sur cette ressource. Connaître une URL, un nom de liaison ou un ID d'objet n'est pas une autorisation.
  • CORS : il s'agit d'une politique d'accès entre origines dans le navigateur, pas d'une authentification. Si cet accès est nécessaire, n'autorisez que les origines prévues et traitez explicitement OPTIONS. Si vous renvoyez dynamiquement une origine validée, ajoutez Vary: Origin ; n'associez pas une origine générique aux identifiants de connexion. curl n'applique pas les contrôles CORS du navigateur.
  • SSRF : n'acceptez pas une URL utilisateur arbitraire pour l'appeler aveuglément avec fetch(). Limitez cette falsification de requêtes côté serveur à l'aide d'un service amont fixe ou d'une liste d'autorisation stricte, de restrictions de protocole et de contrôles des redirections. L'exemple n'envoie aucune requête externe.
  • Secrets et journaux : gardez les identifiants secrets hors du code, de vars, des URL, des fichiers envoyés au navigateur, des erreurs et des journaux. Ne journalisez que le nécessaire au diagnostic ; évitez corps de requête, cookies, jetons et données personnelles.
  • Abus et budgets : limitez les entrées et la fréquence des appels, et fixez des quotas applicatifs pour les opérations coûteuses. Une limite CPU de plateforme ne constitue pas un contrôle complet des dépenses.

Que faut-il observer ?

La sortie locale de console.error apparaît dans le terminal de développement. À distance, Workers Logs et les journaux en temps réel sont notamment disponibles. Vérifiez la configuration, l'échantillonnage, la conservation et la tarification de l'option choisie ; ne supposez pas que chaque requête est conservée indéfiniment.

Après publication, vous devez pouvoir répondre aux questions suivantes : quelle route produit davantage d'erreurs ? Le temps est-il consacré au calcul ou à l'attente de la base ? Une file multiplie-t-elle les tentatives ? Une liaison de stockage échoue-t-elle ? Utilisez des libellés de route stables, des codes d'état et des identifiants de corrélation plutôt que des URL complètes susceptibles de contenir des données personnelles. Diagnostiquez une erreur 500 générique à travers des journaux contrôlés, sans renvoyer la trace de pile au client.

Retour arrière et nettoyage

Confirmez d'abord le nom complet du Worker cible ; celui de la section 7 porte le suffixe -tutorial. Après avoir remplacé le nom fictif par ce nom vérifié, npx wrangler rollback --name YOUR_VERIFIED_WORKER_NAME est une commande distante qui modifie immédiatement le trafic réel : la version choisie reçoit 100 % du trafic, parmi les 100 dernières versions publiées admissibles. Les ressources liées supprimées ne sont pas restaurées, et des changements dans le cycle de vie des classes Durable Object peuvent empêcher le retour arrière. Documentation du retour arrière

Conservez une version précédente identifiable et des structures de données compatibles, vérifiez-les dans un environnement dédié, puis décidez d'un éventuel retour arrière en production. Revenir au code précédent n'annule pas les écritures en base ; les changements de schéma nécessitent un plan distinct de migration et de restauration des sauvegardes.

Terminez le travail local avec Ctrl-C pour arrêter Wrangler. Vous pouvez conserver le projet et la base locale. Pour réinitialiser les données, confirmez d'abord le répertoire de persistance et son appartenance, puis ne supprimez que l'état de cet exercice ; évitez les suppressions récursives trop larges. Les chapitres purement locaux ne créent aucune ressource cloud à supprimer. Si vous avez déployé à la section 7, lancez d'abord npx wrangler delete --env tutorial --dry-run depuis le répertoire conservant cette configuration d'exercice. N'exécutez npx wrangler delete --env tutorial qu'après avoir confirmé que le Worker et les ressources associées appartiennent à l'exercice, puis vérifiez l'invite de confirmation. La commande de suppression peut aussi supprimer des ressources de plateforme associées ; ne l'utilisez jamais pour nettoyer un projet qui réutilise des liaisons de production.

9. Coûts et limites : temps CPU et temps d'attente diffèrent

Ces quotas et tarifs Workers HTTP ont été consultés le 2026-09-12. Ils ne promettent pas qu'une application entière fonctionne gratuitement. Revérifiez la tarification et les limites avant une estimation de production.

ÉlémentValeur documentée et signification
Requêtes Free100 000 requêtes par jour
CPU Free10 ms CPU par invocation, pas un délai de réponse de bout en bout de 10 ms
Coût de base PaidAu moins 5 USD par compte et par mois
Requêtes Paid Standard10 millions par mois incluses ; 0,30 USD par million supplémentaire
CPU Paid Standard30 millions de CPU-ms par mois incluses ; 0,02 USD par million de CPU-ms supplémentaire
Mémoire128 MB par isolate, potentiellement partagés entre requêtes concurrentes ; pas 128 MB par requête
Limite CPU HTTP Paid30 secondes par défaut, configurable jusqu'à 5 minutes ; ce n'est pas une consommation à viser pour chaque requête

Le temps CPU mesure le calcul actif. L'attente de fetch, de KV ou d'une base ne compte généralement pas comme du CPU. Une requête attendant une base pendant 200 ms ne consomme pas nécessairement 200 CPU-ms, mais la requête et l'opération en base peuvent rester facturées. Workers ne facture pas la durée écoulée ; les autres produits ont leurs propres factures.

La durée HTTP dépend du cycle de vie de la connexion ; elle ne permet pas de concevoir des tâches permanentes en arrière-plan. ctx.waitUntil() prolonge le travail de 30 secondes au maximum après une réponse ou une déconnexion. Utilisez une file ou un mécanisme de tâches adapté pour un travail fiable en arrière-plan. Les limites HTTP, des files et des déclencheurs planifiés ne sont pas interchangeables. Limites d'exécution

Les requêtes de fichiers statiques sont normalement gratuites et illimitées, mais la page de tarification précise une exception : avec Workers Caching activé, les requêtes servies depuis le cache sont facturées, y compris celles des fichiers statiques ; les défauts de cache et les contournements consomment aussi du CPU. N'étendez pas la gratuité des fichiers à toute configuration de cache et de routage.

Estimez séparément le nombre de requêtes, la distribution du temps CPU, la configuration du cache statique, les opérations et le stockage D1/KV/R2, les nouvelles tentatives des files et les journaux. Pour l'erreur 1102, recherchez un épuisement du CPU ou de la mémoire ; 1027 concerne le quota quotidien de requêtes Free. Identifiez la cause avant d'optimiser ou de changer d'offre. Une montée en gamme ne remplace pas la correction de boucles infinies, de tampons trop grands ou de tentatives répétées.

Pour les bases du terminal et des serveurs, consultez Outils et méthodes de travail. Si l'application exige finalement un contrôle complet du système, poursuivez avec les fondamentaux d'un VPS personnel.

Explorer les liensOuvrir le réseau