Cloudflare Workers KV en pratique : stockage clé-valeur distribué de A à Z

En regardant la courbe de latence dans le Cloudflare Dashboard. La ligne rouge reste au-dessus de 200 ms — Workers est pourtant en place, le code est déjà minimal, pourquoi chaque requête utilisateur met-elle autant de temps ?
Le problème venait de la base de données. Chaque requête session partait du nœud edge, traversait l’Atlantique vers un datacenter européen, puis revenait. Même si l’exécution Worker ne prend que 5 ms, le réseau absorbe tout le budget.
J’ai compris ensuite : Workers est stateless. Il fallait un stockage qui « vit vraiment en edge » — Cloudflare Workers KV.
Cet article expose les pièges que j’ai rencontrés, les chiffres mesurés et le code écrit. De ce qu’est KV et pourquoi la latence peut descendre sous 10 ms, jusqu’aux implémentations complètes session storage et cache API. Et quand préférer KV, D1 ou R2.
KV en bref — comprendre le stockage edge distribué
En clair, KV est la « mémoire de poche » que Cloudflare fournit aux Workers. Elle n’est pas dans un seul datacenter : elle est répartie sur plus de 300 nœuds edge dans le monde. Un utilisateur à Tokyo peut lire des données déjà présentes à Tokyo ; une requête depuis Francfort peut toucher un cache local.
Cloudflare Workers KV est un stockage clé-valeur distribué mondial conçu pour l’edge computing. Trois caractéristiques essentielles :
Lecture ultra-rapide. Les hot keys en cache affichent une latence entre 500 µs et 10 ms — au premier abord j’étais sceptique, jusqu’à ce qu’un benchmark confirme des valeurs stables en millisecondes simples.
Réplication mondiale. Une écriture est propagée vers tous les nœuds edge. Contrairement à un cluster Redis, le modèle KV est « écrire une fois, lire partout », idéal pour lecture-intensive.
Débit élevé. Une même clé peut supporter des milliers de RPS en lecture, car les données sont en cache edge sans retour systématique à l’origine.
Panorama du stockage Cloudflare
KV n’est qu’une pièce de la matrice de stockage Cloudflare. Vue d’ensemble :
| Service | Modèle | Meilleur cas d’usage | Limite d’écriture | Latence |
|---|---|---|---|---|
| KV | Key-Value | Session, cache, config | 1 RPS/clé | hot keys 500µs-10ms |
| D1 | SQL (SQLite) | Données utilisateur, commandes, rapports | Pas de limite dure | 50-200 ms selon la région |
| R2 | Object Storage | Fichiers, images, vidéos | Pas de limite dure | Téléchargement rapide |
| Durable Objects | Objets stateful | Édition collaborative, WebSocket | Pas de limite dure | Routage vers un nœud précis |
1 RPS/clé, qu’est-ce que ça veut dire ? Chaque clé ne peut être écrite qu’une fois par seconde — la limite la plus critique de KV. On y reviendra en détail.
Quand utiliser KV — guide rapide
Recommandé pour KV :
- Session storage (état de connexion)
- Cache de réponses API (retours d’API tierces)
- Compteurs de rate limiting
- Feature flags / données de configuration
- Redirect mapping (règles de redirection URL)
Déconseillé pour KV :
- Données écrites très fréquemment (compteur temps réel > 1 RPS/clé)
- Données nécessitant du SQL (tables utilisateurs, commandes → D1)
- Gros fichiers (images, vidéos → R2)
- Transactions financières à cohérence forte (→ Durable Objects)
La doc Cloudflare est claire : KV convient aux scénarios « forte lecture, faible modification, cohérence non immédiate ». OpenAuth et d’autres frameworks d’authentification utilisent KV par défaut pour les sessions — implémentation complète plus bas.
Architecture KV — pourquoi c’est si rapide
La vitesse de KV n’est pas magique : c’est le résultat d’une architecture cache à trois niveaux.
Imaginez un dépanneur. Idéal : le produit est sur l’étagère à côté de la caisse (edge cache). Moins bien : en réserve locale, le vendeur va le chercher (regional cache). Pire : entrepôt central, livraison camion (central store).
KV fonctionne ainsi :
Requête → Edge Cache (le plus rapide)
↓ miss
Regional Cache
↓ miss
Central Store (le plus lent)
D’après le blog Cloudflare d’octobre 2025, environ 30 % des requêtes sont résolues dans les couches cache. Un tiers des lectures n’atteint jamais le stockage central — d’où la latence basse.
Performances : doc officielle et mesures
Chiffres de référence Cloudflare :
- Hot keys (accès fréquents) : 500 µs à 10 ms
- Cold keys (premier accès ou rares) : latence plus élevée, retour à l’origine
Le « 500 µs » m’a semblé optimiste. Mesure personnelle :
// Test de latence simple
const start = Date.now();
await env.KV.get("test-key");
const latency = Date.now() - start;
console.log(`Latency: ${latency}ms`);
100 lectures : hot keys en moyenne 5-8 ms. Cold keys : 50 ms+ au premier accès, puis baisse — le cache fonctionne.
En 2025, Cloudflare a refondu KV ; la doc annonce un gain de vitesse ×3, principalement :
- Connexion directe Workers ↔ KV, sans l’ancienne couche Front Line
- Chemin de transfert interne simplifié
Les services Cloudflare dépendant de KV (Turnstile, Waiting Room, etc.) en profitent aussi.
Modèle de cohérence : le prix de la cohérence finale
KV est eventually consistent. Une écriture n’apparaît pas instantanément sur tous les nœuds edge ; la propagation prend quelques secondes à quelques dizaines de secondes en pratique.
Problématique :
- Session écrite après connexion, requête suivante sur un autre nœud edge : session introuvable
- Édition collaborative temps réel : B ne voit pas la modification de A immédiatement
Acceptable :
- Feature flags : quelques secondes de délai OK
- Cache API : TTL de plusieurs minutes, propagation lente sans impact
- Redirect mapping : mise à jour lente, imperceptible pour l’utilisateur
Besoin de cohérence immédiate ? Préférez Durable Objects — état localisé sur un nœud précis.
Configuration pratique avec Wrangler CLI
Passons à la pratique.
Deux étapes : créer un namespace, puis le lier dans wrangler.toml.
Créer un namespace
Un namespace est le « conteneur » KV. Chaque namespace peut contenir un nombre illimité de paires clé-valeur ; le compte est limité à 1000 namespaces (200 → 1000 début 2025).
# Créer le namespace production
wrangler kv namespace create MY_KV
# Sortie type :
# Created namespace with id "abc123def456..."
# Add the following to your wrangler.toml:
# [[kv_namespaces]]
# binding = "MY_KV"
# id = "abc123def456..."
Prévoyez aussi un namespace preview pour le dev local :
# Créer le namespace preview
wrangler kv namespace create MY_KV --preview
# Sortie type :
# Created preview namespace with id "preview_abc123..."
Configuration wrangler.toml
Insérez les id dans wrangler.toml :
name = "my-worker"
main = "src/index.ts"
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123def456..." # namespace production
preview_id = "preview_abc123..." # namespace preview (dev local)
Le nom binding détermine l’accès dans le code Worker :
// binding = "MY_KV" → env.MY_KV dans le code
const value = await env.MY_KV.get("some-key");
REST API vs Workers Binding API
Deux façons d’accéder à KV :
Workers Binding API (recommandé) :
env.MY_KV.get()directement dans le Worker- Pas de requête réseau supplémentaire, le plus rapide
- Gratuit (compté dans le temps d’exécution Worker)
REST API :
- Accès HTTP avec token d’authentification
- Pour systèmes externes
- Soumis aux limites globales REST Cloudflare
Dans la grande majorité des cas, utilisez Binding API. REST API surtout pour :
- Systèmes externes lisant/écrivant KV
- Import batch en CI/CD
- Debug et ops ponctuels
Commandes Wrangler KV courantes
# Écrire
wrangler kv key put --namespace-id=abc123 "my-key" "my-value"
# Lire
wrangler kv key get --namespace-id=abc123 "my-key"
# Supprimer
wrangler kv key delete --namespace-id=abc123 "my-key"
# Lister les clés (filtre par préfixe)
wrangler kv key list --namespace-id=abc123 --prefix="session:"
Utiles en debug ; en production, préférez le code Worker.
Code TypeScript en pratique
Exemples complets et exécutables.
CRUD de base
// src/index.ts
interface Env {
MY_KV: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const path = url.pathname;
// Écrire
if (path === "/put") {
const key = url.searchParams.get("key") || "default";
const value = url.searchParams.get("value") || "hello";
await env.MY_KV.put(key, value);
return new Response(`Saved: ${key} = ${value}`);
}
// Lire
if (path === "/get") {
const key = url.searchParams.get("key") || "default";
const value = await env.MY_KV.get(key);
if (value === null) {
return new Response("Key not found", { status: 404 });
}
return new Response(value);
}
// Supprimer
if (path === "/delete") {
const key = url.searchParams.get("key") || "default";
await env.MY_KV.delete(key);
return new Response(`Deleted: ${key}`);
}
// Lister les clés (avec préfixe)
if (path === "/list") {
const prefix = url.searchParams.get("prefix") || "";
const keys = await env.MY_KV.list({ prefix });
const keyList = keys.keys.map(k => k.name).join("\n");
return new Response(keyList || "No keys found");
}
return new Response("Try /put, /get, /delete, or /list");
},
};
Lancement avec Wrangler :
wrangler dev
# Test écriture
curl "http://localhost:8787/put?key=test&value=helloworld"
# Test lecture
curl "http://localhost:8787/get?key=test"
Session Storage — implémentation complète
Cas d’usage le plus courant de KV :
// src/session.ts
interface SessionData {
userId: string;
email: string;
createdAt: number;
expiresAt: number;
}
interface Env {
SESSION_KV: KVNamespace;
}
const SESSION_TTL = 3600; // expiration 1 heure
class SessionManager {
private kv: KVNamespace;
constructor(kv: KVNamespace) {
this.kv = kv;
}
// Créer une session
async create(userId: string, email: string): Promise<string> {
const sessionId = crypto.randomUUID();
const sessionData: SessionData = {
userId,
email,
createdAt: Date.now(),
expiresAt: Date.now() + SESSION_TTL * 1000,
};
// Écriture KV avec TTL (expiration auto)
await this.kv.put(
`session:${sessionId}`,
JSON.stringify(sessionData),
{ expirationTtl: SESSION_TTL }
);
return sessionId;
}
// Lire une session
async get(sessionId: string): Promise<SessionData | null> {
const raw = await this.kv.get(`session:${sessionId}`);
if (!raw) return null;
try {
return JSON.parse(raw) as SessionData;
} catch {
return null;
}
}
// Supprimer une session (déconnexion)
async delete(sessionId: string): Promise<void> {
await this.kv.delete(`session:${sessionId}`);
}
// Rafraîchir une session (prolonger l'expiration)
async refresh(sessionId: string): Promise<boolean> {
const session = await this.get(sessionId);
if (!session) return false;
session.expiresAt = Date.now() + SESSION_TTL * 1000;
await this.kv.put(
`session:${sessionId}`,
JSON.stringify(session),
{ expirationTtl: SESSION_TTL }
);
return true;
}
}
// Point d'entrée Worker
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const sessionManager = new SessionManager(env.SESSION_KV);
const url = new URL(request.url);
// Connexion (créer session)
if (url.pathname === "/login" && request.method === "POST") {
const body = await request.json();
const sessionId = await sessionManager.create(
body.userId as string,
body.email as string
);
return new Response(JSON.stringify({ sessionId }), {
headers: { "Content-Type": "application/json" },
});
}
// Vérifier session
if (url.pathname === "/verify") {
const sessionId = url.searchParams.get("sessionId");
if (!sessionId) {
return new Response("Missing sessionId", { status: 400 });
}
const session = await sessionManager.get(sessionId);
if (!session) {
return new Response("Session not found", { status: 401 });
}
return new Response(JSON.stringify(session), {
headers: { "Content-Type": "application/json" },
});
}
// Déconnexion
if (url.pathname === "/logout") {
const sessionId = url.searchParams.get("sessionId");
if (sessionId) {
await sessionManager.delete(sessionId);
}
return new Response("Logged out");
}
return new Response("Not found", { status: 404 });
},
};
Points clés :
- TTL auto :
expirationTtlsupprime les données expirées sans nettoyage manuel - Préfixe de clé :
session:pour filtrer et typer les données - Sérialisation JSON : KV ne stocke que des chaînes ; objets complexes via JSON.stringify/parse
Cache de réponses API
Autre cas fréquent : mettre en cache les retours d’API tierces.
// src/api-cache.ts
interface Env {
CACHE_KV: KVNamespace;
}
const DEFAULT_CACHE_TTL = 300; // cache 5 minutes
async function cachedFetch(
kv: KVNamespace,
cacheKey: string,
url: string,
ttl: number = DEFAULT_CACHE_TTL
): Promise<Response> {
// Tentative lecture cache
const cached = await kv.get(cacheKey, "text");
if (cached) {
console.log(`Cache hit: ${cacheKey}`);
return new Response(cached, {
headers: {
"Content-Type": "application/json",
"X-Cache": "HIT",
},
});
}
// Miss : appel API réel
console.log(`Cache miss: ${cacheKey}`);
const response = await fetch(url);
const body = await response.text();
// Écriture cache (cacheTtl optimise les lectures)
await kv.put(cacheKey, body, {
expirationTtl: ttl,
// cacheTtl : cache edge plus long, moins de retours origine
});
return new Response(body, {
headers: {
"Content-Type": "application/json",
"X-Cache": "MISS",
},
});
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const apiUrl = url.searchParams.get("api");
if (!apiUrl) {
return new Response("Missing api parameter", { status: 400 });
}
const cacheKey = `api:${apiUrl}`;
return cachedFetch(env.CACHE_KV, cacheKey, apiUrl);
},
};
Optimisation avec cacheTtl
Paramètre souvent négligé.
cacheTtl contrôle la durée du cache edge. Par défaut 60 secondes : lectures répétées de la même clé servies depuis l’edge sans retour origine.
Pour les données chaudes, augmentez cacheTtl :
// Données config très lues : cache edge plus long
await env.MY_KV.get("config:feature-flags", {
cacheTtl: 3600, // 1 heure de cache edge
});
Même si le central store est inchangé, le nœud edge garde la valeur 1 heure. Idéal pour feature flags où un délai de propagation est acceptable.
KV vs D1 vs R2 — guide de choix
J’ai longtemps hésité entre toutes ces options Cloudflare. Voici un arbre de décision :
Arbre de décision par scénario
Quel type de données ?
├─ Fichiers (images, vidéos, PDF) ?
│ └─ OUI → R2
│
├─ Requêtes SQL (utilisateurs, commandes, jointures) ?
│ └─ OUI → D1
│
├─ Key-value simple, lecture >> écriture ?
│ ├─ Écriture > 1 RPS/clé ?
│ │ └─ OUI → KV inadapté ; D1 ou Durable Objects
│ │
│ └─ NON → KV ✓
│
├─ Cohérence immédiate requise ?
│ └─ OUI → Durable Objects
│ └─ NON → KV peut convenir
│
└─ Incertain ?
└─ Commencez par KV ; ne changez que si insuffisant
Tableau comparatif détaillé
| Dimension | KV | D1 | R2 |
|---|---|---|---|
| Modèle | Key-Value | SQL (SQLite) | Object Storage |
| Requêtes | get/put/delete uniquement | SQL complet | Pas de requête, chemins uniquement |
| Limite écriture | 1 RPS par clé | Pas de limite dure | Pas de limite dure |
| Latence lecture | 500µs - 10ms (hot) | 50-200 ms | Rapide (téléchargement) |
| Cohérence | Eventuelle | Forte (mono-région) | Eventuelle |
| Value max | 25 Mo | Limite ligne SQLite | 5 To par fichier |
| Quota gratuit | 100k lectures/jour | 5 Go + 25M lignes lues | 10 Go stockage |
| Cas typiques | Session, cache, config | Utilisateurs, commandes | Fichiers, images, backup |
Recommandations par scénario
Authentification / Session
→ KV
Session = key-value simple, lecture à chaque requête, écriture rare (login/logout). OpenAuth utilise KV par défaut.
// session:userId → données session
await env.SESSION_KV.put(`session:${sessionId}`, JSON.stringify(session));
Profils utilisateur / commandes
→ D1
Requêtes SQL (« toutes les commandes d’un utilisateur », « CA du mois dernier ») impossibles en get/put KV.
-- Requêtes complexes possibles en D1
SELECT * FROM orders WHERE user_id = ? AND created_at > ?
Images / fichiers
→ R2
Fichiers > 25 Mo ou stockage objet natif.
// Stockage fichier R2
await env.MY_BUCKET.put("images/profile.jpg", imageBuffer);
Rate limiting API
→ KV (avec prudence)
Compteur key-value, mais écriture possible > 1 RPS. Compteur journalier OK ; rate limit précise à la seconde → Durable Objects ou Upstash Redis.
// Rate limiting simple (rafraîchi chaque jour)
const count = parseInt(await env.KV.get(`rate:${userId}`) || "0");
if (count > 100) {
return new Response("Rate limit exceeded", { status: 429 });
}
await env.KV.put(`rate:${userId}`, String(count + 1));
Cache API tierce
→ KV
Lecture fréquente, écriture rare ; TTL 5 minutes sans besoin de cohérence immédiate.
Exemple de combinaison
Un projet peut mixer plusieurs stockages :
interface Env {
SESSION_KV: KVNamespace; // sessions
CACHE_KV: KVNamespace; // cache API
DATABASE_D1: D1Database; // utilisateurs, commandes
FILES_R2: R2Bucket; // fichiers uploadés
}
// Une requête peut tout utiliser :
// 1. SESSION_KV pour la session
// 2. CACHE_KV pour le cache API tierce
// 3. DATABASE_D1 pour les commandes
// 4. FILES_R2 pour l'avatar
C’est la vraie force de l’écosystème Cloudflare.
Optimisation des performances
KV bien utilisé accélère ; mal utilisé, il devient un goulot. Quelques techniques testées en conditions réelles.
1. Ajuster cacheTtl
Par défaut 60 secondes. Pour les hot data, montez la valeur.
// ❌ Comportement par défaut : 60 s cache edge
await env.KV.get("config:feature-flags");
// ✅ Config : cache plus long
await env.KV.get("config:feature-flags", {
cacheTtl: 3600, // 1 heure cache edge
});
Adapté : feature flags, config statique, règles de redirection.
Inadapté : session (état connexion immédiat), compteurs temps réel.
2. Appels parallèles, pas séquentiels
Piège fréquent : plusieurs clés lues l’une après l’autre.
// ❌ Séquentiel : latence cumulée
const user = await env.KV.get(`user:${userId}`);
const settings = await env.KV.get(`settings:${userId}`);
const permissions = await env.KV.get(`permissions:${userId}`);
// latence totale = 3 × latence unitaire
// ✅ Parallèle
const [user, settings, permissions] = await Promise.all([
env.KV.get(`user:${userId}`),
env.KV.get(`settings:${userId}`),
env.KV.get(`permissions:${userId}`),
]);
// latence ≈ la plus lente des trois
Les appels KV sont asynchrones. Promise.all compresse la latence.
Mesure : 3 clés, séquentiel ~20 ms, parallèle ~8 ms.
3. Stratégie hot keys
Les performances KV dépendent du « chaud » des clés.
// ❌ Clés trop dispersées, cold keys
await env.KV.get(`session:${userId}`); // un seul utilisateur
// ✅ Hot key pour données partagées
await env.KV.get("config:global-flags"); // tous les utilisateurs
Ne regroupez pas tout dans une clé. Règle :
- Données privées : une clé par utilisateur (session, profil)
- Données globales : une hot key (config, flags, redirections)
4. Organisation des namespaces
1000 namespaces par compte. Isolez par type :
# wrangler.toml
[[kv_namespaces]]
binding = "SESSION_KV"
id = "xxx" # sessions
[[kv_namespaces]]
binding = "CACHE_KV"
id = "yyy" # cache API
[[kv_namespaces]]
binding = "CONFIG_KV"
id = "zzz" # configuration
Avantages :
- Nettoyage isolé : vider CACHE_KV sans toucher SESSION_KV
- TTL différents : session courte, config longue
- Monitoring séparé dans le Dashboard
5. Opérations batch
list() avec préfixe :
// Lister toutes les clés session
const result = await env.SESSION_KV.list({ prefix: "session:" });
for (const key of result.keys) {
console.log(key.name);
}
// Pagination si beaucoup de clés
if (!result.list_complete) {
const next = await env.SESSION_KV.list({
prefix: "session:",
cursor: result.cursor,
});
}
Nettoyage batch (prudence) :
// Supprimer toutes les sessions (à utiliser avec discernement)
const keys = await env.SESSION_KV.list({ prefix: "session:" });
for (const key of keys.keys) {
await env.SESSION_KV.delete(key.name);
}
Attention : consomme beaucoup de quota d’écriture.
Tarification et limites — maîtriser les coûts
Tarification KV généreuse, mais quelques limites peuvent faire planter votre app.
Free Plan vs Paid Plan
| Indicateur | Free Plan | Paid Plan ($5/mois) |
|---|---|---|
| Lectures | 100 000 / jour | Illimitées (facturées) |
| Écritures | 1 000 / jour | Illimitées (facturées) |
| Suppressions | 1 000 / jour | Illimitées (facturées) |
| Listes | 1 000 / jour | Illimitées (facturées) |
| Stockage | 1 Go | Illimité (facturé) |
| Namespaces | 1000 | 1000 |
Free suffit pour projets perso et tests. Production : Paid à $5/mois pour lectures illimitées (pay-as-you-go), plus d’écritures et monitoring Dashboard.
Write Rate Limit — la limite critique
Chaque clé unique : maximum 1 écriture par seconde (1 RPS)
Dépassement = erreur directe.
// ❌ Écritures rapides échouent
for (let i = 0; i < 10; i++) {
await env.KV.put("counter", String(i)); // 2e+ échec
}
// ✅ Clés dispersées dans le temps
await env.KV.put(`counter:${Math.floor(Date.now() / 1000)}`, value);
// une nouvelle clé par seconde
KV réplique chaque écriture mondialement ; Cloudflare limite pour protéger l’infrastructure.
Stratégies :
- Clés avec horodatage :
counter:timestamp - UUID par écriture
- D1 ou Durable Objects si écriture haute fréquence obligatoire
Limite de taille des values
Maximum 25 Mo (10 Mo → 25 Mo début 2025).
// ❌ > 25 Mo = erreur
const largeData = generateBigString(30_000_000); // 30 Mo
await env.KV.put("large-key", largeData); // Error!
// ✅ Gros volumes → R2
await env.R2_BUCKET.put("large-key", largeData);
25 Mo suffit pour session, config et cache ; JSON volumineux ou fichiers → R2.
Stratégie de namespaces
1000 namespaces par compte (200 → 1000 en 2025).
// Groupement par fonction
SESSION_KV // sessions
CACHE_KV // cache API
CONFIG_KV // configuration
RATE_LIMIT_KV // rate limiting
Namespaces épuisés ? Préfixes dans un seul namespace :
// Isolation par préfixe
await env.KV.put("session:user1", data);
await env.KV.put("cache:api1", data);
await env.KV.put("config:flags", data);
Formule d’estimation des coûts
Avec Paid plan :
Coût mensuel = $5 (base) + lectures + écritures + stockage
Lectures = nb lectures × $0,01 / 100 000
Écritures = nb écritures × $1,00 / 1 000 000
Stockage = taille × $0,50 / Go
Exemple : 100 000 requêtes/jour
- Lectures : 100 000 × 30 = 3M/mois ≈ $0,30
- Écritures : 1 000 × 30 = 30k/mois ≈ $0,03
- Stockage : 10 Mo ≈ $0,005
- Total : $5 + $0,33 ≈ $5,35/mois
Typique Cloudflare : abordable.
Conclusion
En une phrase : KV est la « mémoire de poche » de Workers — session, cache, config, lecture >> écriture.
Choisir KV si :
- Données key-value simples
- Lecture bien plus fréquente que l’écriture
- Cohérence immédiate non requise
- ≤ 1 écriture/seconde par clé
Passer à D1 si :
- Requêtes SQL
- Jointures complexes
- Écriture possible > 1 RPS
Passer à R2 si :
- Fichiers, images, vidéos
- Value > 25 Mo
Passer à Durable Objects si :
- Cohérence immédiate
- Édition collaborative temps réel
Prochaine étape : brancher KV sur votre projet Workers. Commencez par session storage — le code ci-dessus est prêt à l’emploi. La doc Cloudflare est détaillée ; cette série cloudflare-bindui couvre D1 et R2 pour compléter la matrice de stockage.
FAQ
Quelle est la limite d'écriture de Cloudflare Workers KV ?
KV convient-il au stockage des sessions utilisateur ?
Quelle différence entre KV et D1 ? Lequel choisir ?
• KV : modèle Key-Value, hot keys 500µs-10ms, limite 1 RPS/clé
• D1 : modèle SQL (SQLite), requêtes complexes, pas de limite d'écriture stricte
Choix : SQL → D1 ; key-value simple et lecture-intensive → KV.
Pourquoi KV atteint-il une latence de 500µs-10ms ?
À quoi sert le paramètre cacheTtl ?
Quelle taille maximale pour une value KV ?
15 min de lecture · Publié le: 22 avr. 2026 · Mis à jour le: 27 juil. 2026
Cloudflare Full Stack
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Guide complet Astro sur Cloudflare : configuration SSR et accès Chine ×3 plus rapide
Déployez Astro sur Cloudflare Pages de zéro, configurez les trois modes de l'adaptateur SSR, et appliquez trois stratégies d'optimisation pour l'accès depuis la Chine (IP optimisées, CNAME, résolution par opérateur) — latence réduite jusqu'à ×3 en conditions réelles
Partie 18 sur 23
Suivant
Cloudflare Dynamic Workers : le secret d'un sandbox Agent IA 100× plus rapide que les conteneurs
Cloudflare Dynamic Workers utilise des V8 Isolates pour le sandbox des Agents IA : démarrage 100× plus rapide que les conteneurs, efficacité mémoire 10 à 100× supérieure. Analyse approfondie des principes techniques, mécanismes de sécurité, API pratiques et rapport coût-bénéfice, avec recommandations complètes de choix technologique.
Partie 20 sur 23



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire