Skip to content

Type de ressource : Binding Cloudflare (KV / Queue / R2 / Service / Secret)
Fichier source : services/[worker-name]/wrangler.toml
Statut : [Actif / Déprécié / En développement]

[Description concise du rîle de ce binding dans l’architecture L3]

  • [Objectif principal : ex. stocker temporairement les soumissions de formulaires en cas de panne CRM]
  • [BĂ©nĂ©fice pour l’architecture : ex. rĂ©silience asynchrone sans bloquer l’utilisateur]
Propriété Valeur
Type de binding [KV / Queue / R2 / Service / Secret / D1 / Durable Object]
Nom du binding [BINDING_NAME]
Nom de la ressource [resource-name]
Environnements [Production / Staging / Preview]
Workers consommateurs [Liste des Workers qui utilisent ce binding]
[Worker Producteur]
│ ‱ Écriture / Envoi
▌
[Binding Cloudflare]
│ ‱ Stockage / File d'attente
▌
[Worker Consommateur]
│ ‱ Lecture / Consommation
▌
[Action / Réponse]
Composant RĂŽle Type
[Worker producteur] Écriture dans le binding Worker L3
[Binding] Stockage / File d’attente Cloudflare Service
[Worker consommateur] Lecture / Consommation Worker L3
services/[worker-name]/wrangler.toml
# Exemple pour KV
[[kv_namespaces]]
binding = "KV_BINDING"
id = "your-kv-namespace-id"
preview_id = "your-preview-kv-namespace-id"
# Exemple pour Queue (producer)
[[queues.producers]]
queue = "queue-name"
binding = "QUEUE_BINDING"
# Exemple pour Queue (consumer)
[[queues.consumers]]
queue = "queue-name"
max_batch_size = 10
max_batch_timeout = 30
# Exemple pour R2
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "bucket-name"
preview_bucket_name = "bucket-name-staging"
# Exemple pour Service Binding
[[services]]
binding = "SERVICE_BINDING"
service = "service-name"
environment = "production"
Terminal window
# Création d'un namespace KV
wrangler kv:namespace create "KV_BINDING" --env production
wrangler kv:namespace create "KV_BINDING" --env staging
# Création d'une Queue
wrangler queues create queue-name --env production
wrangler queues create queue-name --env staging
# Création d'un bucket R2
wrangler r2 bucket create bucket-name
# Liaison d'un bucket R2 Ă  un Worker
wrangler r2 bucket link bucket-name --binding R2_BUCKET
Variable Description Obligatoire Valeur par défaut
[Variable] [Description] [✅/❌] [Valeur]
// Interface Env du Worker consommateur
export interface Env {
// KV
KV_BINDING: KVNamespace;
// Queue
QUEUE_BINDING: Queue;
// R2
R2_BUCKET: R2Bucket;
// Service
SERVICE_BINDING: Fetcher;
// Secret
SECRET_NAME: string;
}
// Exemple : Écriture dans KV
await env.KV_BINDING.put('key', 'value', {
expirationTtl: 3600, // 1 heure
metadata: { createdAt: new Date().toISOString() }
});
// Exemple : Envoi dans une Queue
await env.QUEUE_BINDING.send({
email: 'user@example.com',
message: 'Hello',
submittedAt: new Date().toISOString()
});
// Exemple : Upload vers R2
await env.R2_BUCKET.put('path/to/file.jpg', fileContent, {
httpMetadata: { contentType: 'image/jpeg' },
customMetadata: { uploadedBy: 'user-123' }
});
// Exemple : Appel Ă  un Service Binding
const response = await env.SERVICE_BINDING.fetch('https://service-name/path', {
method: 'POST',
body: JSON.stringify({ data: 'value' })
});
export default {
async queue(batch: MessageBatch, env: Env, ctx: ExecutionContext): Promise<void> {
for (const message of batch.messages) {
try {
const payload = message.body as { email: string; message: string };
// Traitement du message
await processMessage(payload, env);
// Acknowledgement implicite (message retiré de la queue)
message.ack();
} catch (error) {
console.error('Erreur de traitement du message', error);
// Retry ou dead letter queue
message.retry();
}
}
},
};

Contexte : Le Worker cms-webhook-receiver utilise KV pour éviter les rebuilds multiples en cascade.

// Pose d'un lock pour 2 minutes
const lockKey = 'sanity-rebuild-lock';
const isLocked = await env.WEBHOOK_LOCK_KV.get(lockKey);
if (isLocked) {
return new Response(JSON.stringify({
status: 'ignored',
message: 'Rebuild déjà planifié (Debounced)'
}), { status: 200 });
}
await env.WEBHOOK_LOCK_KV.put(lockKey, 'locked', { expirationTtl: 120 });

Configuration :

  • ClĂ© : sanity-rebuild-lock
  • TTL : 120 secondes (2 minutes)
  • Rationale : ProtĂ©ger les quotas CI/CD de l’hĂ©bergeur

Contexte : Le Worker form-handler utilise une Queue pour re-tenter l’envoi au CRM en cas de panne.

try {
const crmRes = await fetch(env.CRM_ENDPOINT_URL, {
method: 'POST',
headers: { 'Authorization': `Bearer ${env.CRM_API_KEY}` },
body: JSON.stringify(crmPayload),
});
if (!crmRes.ok) throw new Error(`Erreur HTTP CRM: ${crmRes.status}`);
} catch (crmError) {
console.error('Échec de synchro CRM en direct. Envoi en queue...', crmError);
await env.SUBMISSIONS_QUEUE.send(crmPayload);
}

Configuration :

  • Nom de la Queue : form-submissions-queue
  • Binding : SUBMISSIONS_QUEUE
  • Rationale : RĂ©silience asynchrone sans bloquer l’utilisateur

Contexte : Les Workers media-upload, media-cleanup et sanity-backup utilisent R2 pour stocker les médias et les backups.

// Upload d'un média
await env.R2_BUCKET.put(`medias/images/blog/${Date.now()}-${filename}`, fileContent, {
httpMetadata: { contentType: 'image/webp' }
});
// Listing des objets
const objects = await env.R2_BUCKET.list({ prefix: 'medias/' });
// Suppression
await env.R2_BUCKET.delete('medias/images/blog/old-image.webp');
// Streaming vers R2 (backup)
await env.R2_BACKUP_BUCKET.put(backupKey, exportRes.body, {
customMetadata: { exportedAt: new Date().toISOString() }
});

Configuration :

  • Bucket mĂ©dias : pub-medias
  • Bucket backups : backups-sanity
  • Rationale : Stockage Edge natif, coĂ»ts maĂźtrisĂ©s, performance optimale
Binding AccĂšs Rationale
KV Workers uniquement Pas d’accùs direct depuis le client
Queue Workers uniquement Pas d’accùs direct depuis le client
R2 Workers + URLs publiques/signées Médias publics, documents sensibles signés
Secrets Workers uniquement Jamais exposés cÎté client
  • ✅ Les bindings sont accessibles uniquement depuis les Workers (pas depuis le navigateur)
  • ✅ Les secrets sont injectĂ©s via wrangler secret put (jamais dans le code source)
  • ✅ Les buckets R2 publics sont protĂ©gĂ©s par le proxy Cloudflare (WAF, DDoS)
  • ✅ Les URLs signĂ©es ont une durĂ©e de vie limitĂ©e (1h Ă  24h max)
  • ✅ Les Queues ne sont pas accessibles publiquement ( Workers uniquement)
Terminal window
# Rotation d'un secret
wrangler secret put SECRET_NAME --env production
wrangler secret put SECRET_NAME --env staging
# Liste des secrets
wrangler secret list --env production
Binding Limite Rationale
KV 100 000 lectures/s, 1 000 écritures/s Quota Cloudflare
Queue 5 000 messages/s, 10 MB max par message Quota Cloudflare
R2 10 000 000 requĂȘtes/mois (Free), IllimitĂ© (Paid) Quota Cloudflare
Service Binding 50 sous-requĂȘtes par Worker Limite Workers
  • ✅ Utiliser KV pour les donnĂ©es frĂ©quemment lues et rarement modifiĂ©es
  • ✅ Utiliser les Queues pour le traitement asynchrone (Ă©vite les timeouts)
  • ✅ Utiliser R2 pour le stockage de fichiers (pas de limite de taille)
  • ✅ Utiliser le streaming HTTP pour les gros volumes (Ă©vite OOM)
  • ✅ Mettre en cache les donnĂ©es KV avec TTL appropriĂ©
Binding ModÚle de coût Estimation mensuelle
KV $0.50/10M lectures, $5/1M écritures ~$5-10
Queue $0.40/1M messages ~$2-5
R2 $0.015/GB/mois, $0.36/1M requĂȘtes ~$10-20
Service Binding Inclus dans le coût Workers $0 supplémentaire
Binding MĂ©trique Seuil d’alerte Canal
KV Latence p95 > 50ms Slack
Queue Profondeur de la queue > 1000 messages PagerDuty
Queue Taux d’erreur > 5% sur 5 min Slack
R2 Espace utilisé > 80% du quota Email
R2 Coût mensuel > $50 Email
Terminal window
# Inspection KV
wrangler kv:key list --binding=KV_BINDING --env production
wrangler kv:key get --binding=KV_BINDING "key" --env production
# Inspection Queue
wrangler queues info queue-name --env production
# Inspection R2
wrangler r2 object list bucket-name --prefix medias/
# Logs en temps réel
wrangler tail [worker-name] --env production
SymptĂŽme Cause probable Solution
“Binding not found” Binding mal configurĂ© dans wrangler.toml VĂ©rifier la configuration et redĂ©ployer
“Queue full” Consommateur trop lent Augmenter max_batch_size ou ajouter des consommateurs
“KV rate limit exceeded” Trop de lectures/Ă©critures Mettre en cache ou optimiser les accĂšs
“R2 access denied” Permissions insuffisantes VĂ©rifier les permissions du token API
“Secret not found” Secret non injectĂ© ExĂ©cuter wrangler secret put
Terminal window
# Test KV
wrangler kv:key put --binding=KV_BINDING "test-key" "test-value" --env staging
wrangler kv:key get --binding=KV_BINDING "test-key" --env staging
# Test Queue (envoi manuel)
wrangler queues send queue-name --data '{"test": "data"}' --env staging
# Test R2
wrangler r2 object put bucket-name/test.txt --file=test.txt
wrangler r2 object get bucket-name/test.txt
  • ✅ Utiliser KV pour les donnĂ©es temporaires (locks, cache, sessions)
  • ✅ Utiliser les Queues pour le traitement asynchrone (formulaires, webhooks)
  • ✅ Utiliser R2 pour le stockage de fichiers (mĂ©dias, backups)
  • ✅ SĂ©parer les buckets par environnement (production, staging)
  • ✅ Documenter les bindings dans ce fichier
  • ✅ Typer strictement les bindings dans l’interface Env
  • ✅ GĂ©rer les erreurs de maniĂšre explicite (try/catch)
  • ✅ Utiliser le streaming pour les gros volumes (R2)
  • ✅ Mettre en cache les donnĂ©es KV avec TTL appropriĂ©
  • ✅ Logger les opĂ©rations critiques pour l’audit
  • ✅ Minimiser les lectures/Ă©critures KV (batch si possible)
  • ✅ Utiliser les Queues pour Ă©viter les timeouts
  • ✅ Utiliser le streaming HTTP pour R2 (Ă©vite OOM)
  • ✅ Surveiller les mĂ©triques de performance (latence, dĂ©bit)
  • ✅ Optimiser les coĂ»ts (nettoyage rĂ©gulier, lifecycle rules)
  • ✅ Ne jamais exposer les bindings cĂŽtĂ© client
  • ✅ Injecter les secrets via wrangler secret put
  • ✅ Rotation rĂ©guliĂšre des secrets (tous les 90 jours)
  • ✅ Utiliser des URLs signĂ©es pour les documents sensibles
  • ✅ Auditer les accĂšs aux buckets R2
  • [Évolution 1 : ex. Migration vers D1 pour les donnĂ©es relationnelles]
  • [Évolution 2 : ex. Ajout de Durable Objects pour les sessions utilisateur]
  • [Évolution 3 : ex. ImplĂ©mentation d’une dead letter queue pour les messages Ă©chouĂ©s]
  • ❌ KV ne supporte pas les transactions (pas d’atomicitĂ© multi-clĂ©s)
  • ❌ Les Queues ont une limite de 10 MB par message
  • ❌ R2 ne supporte pas nativement la transformation d’images (nĂ©cessite Cloudflare Images)
  • ❌ Les Service Bindings ont une limite de 50 sous-requĂȘtes par Worker
  • Documentation Cloudflare KV : Getting Started
  • Documentation Cloudflare Queues : Getting Started
  • Documentation Cloudflare R2 : Getting Started
  • Documentation Service Bindings : Workers Services
  • DAT L3 : §5 - Microservices MĂ©tiers (Cloudflare Workers DĂ©diĂ©s)
  • DAT L3 : §6 - Structure Monorepo, Wrangler & Configuration
  • Workers consommateurs :
    • services/form-handler/
    • services/cms-webhook-receiver/
    • services/media-upload/
    • services/media-cleanup/
    • services/sanity-backup/
  • Fichiers concernĂ©s :
    • services/[worker-name]/wrangler.toml
    • Configuration Dashboard Cloudflare → KV / Queues / R2
Date Version Description Auteur
YYYY-MM-DD 1.0 Création initiale [Nom]
YYYY-MM-DD 1.1 [Modification] [Nom]
---
**Points clés de ce template :**
- Couvre tous les types de bindings Cloudflare (KV, Queue, R2, Service, Secret)
- Détaille la configuration Wrangler complÚte pour chaque type
- Inclut des cas d'usage spécifiques au projet (debouncing webhooks, fallback formulaires, stockage médias)
- Documente les limites, les coûts et les optimisations
- Fournit les commandes de debug et de monitoring
- Sépare clairement les bonnes pratiques par catégorie (architecture, code, performance, sécurité)
Edit page

Last updated: