Les trois primitives de stockage de Cloudflare (KV, R2 et Cache API) apparaissent ensemble dans la documentation et partagent le même environnement d'exécution, ce qui donne l'impression qu'elles constituent des alternatives au même problème. Ce n’est pas le cas. Chacun a été construit avec une architecture différente, pour une charge de travail différente, avec un modèle de coûts différent. Utiliser le mauvais outil n’est pas seulement inefficace : dans certains cas, cela ne fonctionne tout simplement pas.
La confusion est compréhensible. Tous les trois « stockent des données ». Mais la distinction pertinente ne réside pas dans ce qu'ils font dans l'abstrait : il s'agit de la façon dont chacun fonctionne dans un trafic réel, de son coût à grande échelle et des garanties qu'il offre.
KV : le magasin mondial pour les petites données fréquemment lues
KV est un magasin clé-valeur distribué à l’échelle mondiale. Les écritures sont envoyées vers un magasin central et se propagent à plus de 300 PoP en 60 secondes maximum. Les lectures arrivent en moins de millisecondes si la clé est mise en cache dans le PoP le plus proche, ou en environ 20 ms si elle doit être récupérée depuis le magasin central.
Le modèle de coût privilégie les relevés en volume : 0,50 $ par million de relevés après les 10 premiers millions de relevés mensuels gratuits. Les écritures coûtent le même 0,50 $ par million, mais avec seulement 1 million gratuit. La limite maximale par valeur est de 25 Mo.
KV fonctionne bien pour les données rarement écrites et lues massivement : configuration du produit, indicateurs de fonctionnalités, modèles, index de contenu, jetons de session avec TTL. Cela fonctionne mal pour tout ce qui change fréquemment ou nécessite une cohérence immédiate – une cohérence éventuelle avec une fenêtre allant jusqu'à 60 secondes et l'absence d'opérations atomiques sont de réelles limitations, pas des détails de documentation.
R2 : stockage d'objets sans frais de sortie
R2 est le stockage objet de Cloudflare, équivalent fonctionnel à S3. Il a été conçu pour les fichiers volumineux : images, vidéos, sauvegardes, exportations de données, ressources statiques. La différence concurrentielle par rapport à S3 réside dans l'absence de frais de sortie : vous ne payez pas pour transférer des données de R2 vers Internet, ce qui dans S3 est l'une des lignes les plus pénibles de la facture.
Le coût de stockage est de 0,015 $/Go-mois. Chaque opération de lecture (GET) dans R2 compte comme une requête — il n'y a pas de cache automatique global comme dans KV. Si vous OBTENEZ un objet R2 dans chaque requête Worker, vous payez pour chaque requête plus le temps de latence de chaque GET. Cela rend R2 inadapté aux données à haute fréquence de lecture par requête.
La combinaison correcte consiste à utiliser R2 pour le fichier et KV (ou l'API Cache) pour l'index ou la version mise en cache. Un Worker qui sert des images peut stocker le binaire dans R2 et conserver un JSON dans KV avec des URL signées, des métadonnées et des en-têtes HTTP. Ainsi, une lecture fréquente accède à KV en moins de millisecondes, et R2 n'est utilisé que pour les téléchargements et la génération d'URL.
La limite par objet dans R2 n'est pas la même que dans KV : les fichiers de plusieurs Go sont pris en charge. Pour KV avec son maximum de 25 Mo par valeur, R2 est la destination naturelle de toutes les données dépassant ce seuil.
API Cache : le cache de réponses HTTP par PoP
L'API Cache stocke Response objets dans le cache HTTP du PoP actuel. C'est gratuit, sans quotas d'opérations, et fonctionne comme une couche de mise en cache sur les réponses HTTP, et non comme un magasin d'état partagé.
Le détail critique qui le différencie de KV est la portée : l'API de cache est par PoP, et non globale. Un accès au cache dans le PoP de São Paulo n'affecte pas le PoP de Francfort. Si un Worker à Francfort n'a jamais reçu de demande pour cette URL, le cache sera froid à Francfort, quel que soit le nombre de fois que São Paulo a envoyé cette réponse à partir du cache.
Autre limite : le contenu de l'API Cache peut être expulsé par le PoP à tout moment en raison de la pression du LRU. Il n'y a aucune garantie de persistance entre les requêtes : la requête suivante pour la même ressource peut rencontrer le cache froid, même si la requête précédente l'a rempli.
L'API Cache fonctionne bien pour dédupliquer les requêtes vers des API tierces dans un court laps de temps : vous la récupérez une fois, mettez Response en cache pendant 30 secondes et les requêtes suivantes dans le même PoP réutilisent la réponse sans appeler l'API en amont. Il sert également à mettre en cache les réponses coûteuses en calcul qui sont demandées en rafales dans le même PoP.
Ce qui ne fonctionne pas : utiliser l'API Cache comme état partagé entre Workers ou entre régions. Deux instances Worker dans des PoP différents ne verront pas le même état du cache. Pour l'état partagé, KV est la solution.
La matrice anti-modèle
Utiliser R2 pour la configuration des applications est l'erreur la plus courante parmi les équipes arrivant de S3. Sur S3, il est courant de stocker config.json dans un compartiment et de le lire au démarrage de l'application : le serveur dure des heures ou des jours, donc un GET à chaque redémarrage est bon marché. Dans Workers, chaque isolat peut être créé et détruit fréquemment. Chaque GET vers R2 a la latence d’une requête réseau et compte comme une opération facturée. Pour la configuration, KV avec mise en cache au niveau du module est le modèle correct.
L'utilisation de KV pour les fichiers vidéo ou les grands ensembles de données est l'autre extrême. La limite de 25 Mo par valeur crée déjà des problèmes immédiats pour tout actif de taille réelle. Mais au-delà de cette limite, le coût d'écriture sur KV est prohibitif pour les fichiers qui arrivent fréquemment via le téléchargement par l'utilisateur. R2 à 0,015 $/Go par mois est plusieurs ordres de grandeur moins cher pour le stockage de fichiers volumineux.
L’utilisation de l’API Cache pour tout type d’état qui doit être cohérent entre les PoP est une source garantie de comportement erratique. Le symptôme typique est un bug qui apparaît « parfois » – parce que le PoP qui a servi la requête précédente avait le cache rempli, et le PoP qui a servi celle-ci ne l'a pas été. L'API de cache ne remplace pas KV pour les données globales.
Comment choisir
La décision commence par le type de données et la fréquence d’accès. Les petites données, lues plusieurs fois par seconde, nécessitent une distribution mondiale : KV. Fichier volumineux, écrit par téléchargement et lu à fréquence faible à modérée : R2. Réponse HTTP qui change rarement et peut être locale à l'API PoP : Cache.
Le coût confirme ou rejette le choix. Si le volume d’écritures est élevé, KV devient cher. Si le volume de GET individuels par fichier est élevé, R2 devient coûteux et lent. Si vous avez besoin d'une cohérence entre PoP, l'API Cache ne fera pas l'affaire.
La combinaison des trois est le bon modèle
Le modèle qui apparaît le plus souvent dans les architectures matures avec Workers est une combinaison délibérée. R2 stocke le binaire. KV stocke l'index, les métadonnées et l'URL signée de courte durée. L'API de cache déduplique les requêtes en rafale vers le même PoP. Chaque couche fait ce pour quoi elle a été conçue, et le résultat est une pile de stockage qui fonctionne bien et coûte ce qu'elle devrait coûter.
Le piège tente de se simplifier en une seule primitive. Cloudflare propose les trois car chacun résout un problème différent. Comprendre la frontière entre eux est ce qui sépare une implémentation qui fonctionne en développement de celle qui survit au trafic réel.
A lire aussi
-Cloudflare KV : Que signifie une distribution mondiale lorsque vous devez écrire
- Invalidation du cache dans KV : le problème que personne ne résout avec élégance
- Cloudflare Load Balancing et Geo Steering : quand le DNS devient une couche de trafic intelligente
- KV en production : les schémas qui marchent et ceux qui trompent au début
- [KV pour la limitation de débit, les indicateurs de fonctionnalités et la configuration distribuée : où ça marche et où ça casse7
- Ouvriers + D1 + KV + R2 : composer des liaisons dans le même service
