R2: almacenamiento de objetos sin peaje de salida
R2 es el almacenamiento de objetos de Cloudflare: un almacén plano de clave a bytes, hablado con la misma API que definió Amazon S3, pero con una diferencia que reordena la economía de la nube —no cobra por el egress, los datos que salen hacia internet—. Vemos qué es el almacenamiento de objetos, por qué R2 adopta la API de S3, cómo se crea un bucket y por qué el egress cero no es un descuento sino un cambio de modelo que disuelve la gravedad de los datos.
Toda aplicación acaba necesitando guardar bytes que no caben en una base de datos: imágenes, vídeos, PDF, copias de seguridad, lo que sube un usuario. Ese trabajo tiene un nombre —almacenamiento de objetos— y desde 2006 tiene un dueño de facto: Amazon S3, que convirtió su API en el latín de la industria. R2 es la respuesta de Cloudflare, y su jugada es astuta: habla el mismo idioma que S3 para que tus herramientas no noten el cambio, pero rompe la regla más lucrativa del modelo —el peaje que se cobra por sacar tus propios datos hacia internet—. Esa sola diferencia no es un descuento marginal; es lo que convierte a R2 en un lugar distinto donde poner los bytes.
- Definir el almacenamiento de objetos como un almacén plano de clave a bytes con metadatos, accedido por HTTP.
- Entender por qué R2 adopta la API de S3 y qué compra esa compatibilidad.
- Crear un bucket y distinguir sus dos puertas: el binding interno y la API S3 externa.
- Razonar el giro económico del egress cero: de un coste que sigue al tráfico a uno que solo sigue a lo almacenado.
Qué es el almacenamiento de objetos
Antes de mirar a R2 conviene situar la categoría a la que pertenece, porque es la más joven de las tres formas canónicas de guardar bytes. El almacenamiento de bloques —el disco de una máquina— ofrece un array de sectores que un sistema de ficheros organiza por encima. El almacenamiento de ficheros —un NFS, un recurso compartido— expone una jerarquía de carpetas con permisos y bloqueos. El de objetos renuncia a ambos y ofrece algo más humilde y, por eso mismo, más escalable: un diccionario gigante. Una clave, que es solo una cadena de texto, apunta a un objeto —una secuencia opaca de bytes acompañada de metadatos—.
Ese minimalismo es deliberado. No hay carpetas de verdad: la barra en fotos/2026/gato.png es parte de la clave, no una estructura real, y la ilusión de directorios se reconstruye a posteriori con un delimiter al listar. No hay reescritura parcial: no editas el byte 500 de un objeto, reemplazas el objeto entero. No hay bloqueo de ficheros ni cursores. El contrato se reduce a cuatro gestos —pon esta clave con estos bytes, dame la clave, bórrala, lista las claves— servidos por HTTP.
Lo que parece una limitación es la fuente del poder. Al prohibir la edición en sitio y los accesos aleatorios, el sistema se libera de coordinar escrituras concurrentes sobre el mismo dato y puede repartir objetos por miles de discos sin un punto central que arbitre. Por eso el almacenamiento de objetos escala a exabytes y cuesta céntimos por gigabyte, mientras un disco de bloques o un servidor de ficheros topan pronto con su techo. Es el almacén ideal para bytes grandes, inmutables y numerosos: precisamente los que desbordan una base de datos.
Dos propiedades rematan el retrato. R2 es fuertemente consistente: en cuanto un put termina, cualquier lectura posterior desde cualquier parte del mundo ve la versión nueva, sin la ventana de datos rancios que arrastró S3 en sus primeros años. Y los límites dibujan la intención del diseño: la clave admite hasta 1024 bytes, los metadatos de usuario hasta 8192, y un objeto llega hasta 5 TiB. Números generosos que casi nunca estorban, pero que hablan claro —claves como rutas legibles, metadatos como etiquetas breves, objetos tan grandes como haga falta—.
R2 habla el idioma de S3
S3 no solo inauguró esta categoría en la nube; definió su vocabulario. Bucket, key, PUT, GET, multipart, URL presignada: esas palabras son de S3, y una generación entera de SDK, herramientas de backup, motores de datos y tutoriales asume esa API como el suelo firme sobre el que pisa. Cloudflare tomó una decisión estratégica en vez de estética: no inventar una interfaz nueva y supuestamente mejor, sino implementar la API de S3 tal cual. Apuntas tu cliente de siempre a otro endpoint y funciona.
// El mismo cliente de S3 de siempre, creyendo que habla con AWS.
const s3 = new S3Client({
region: "auto",
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
credentials: { accessKeyId, secretAccessKey },
});
Esa compatibilidad no es cosmética, es la vía de escape del lock-in. Migrar de S3 a R2 no significa reescribir la aplicación: significa cambiar una URL de endpoint y un par de credenciales. Herramientas que llevan una década asumiendo S3 —rclone, boto3, el aws-sdk— hablan con R2 sin enterarse de que cambiaron de proveedor.
No confundas esta puerta con el binding. La API S3 mira al mundo exterior y usa claves de acceso; el binding env.BUCKET mira a tu Worker y usa una capacidad declarada. Ambas alcanzan el mismo bucket, pero la interna es más simple y más segura, y es la que usarás desde el edge.
Crear un bucket y las dos puertas
Poner en pie un bucket es una línea. Wrangler lo crea y, a partir de ahí, existe como recurso de tu cuenta:
wrangler r2 bucket create mi-bucket
Para que tu Worker lo alcance sin credenciales, lo declaras como binding —la misma capacidad que ya conoces del resto de la plataforma—. La lista de r2_buckets es a la vez el permiso y el mapa de qué almacenes toca este Worker:
{
"r2_buckets": [
{ "binding": "BUCKET", "bucket_name": "mi-bucket" }
]
}
Con eso, env.BUCKET es la puerta interna: tu código del edge lee y escribe por ella, sin URL ni claves, y la próxima lección la recorre entera. La puerta externa es la API S3 con claves de acceso, para las herramientas de fuera de Cloudflare. Un solo almacén, dos accesos con públicos distintos.
// La puerta interna, desde el Worker: una capacidad, no una credencial.
await env.BUCKET.put("saludo.txt", "hola");
const obj = await env.BUCKET.get("saludo.txt");
Wrangler también sube objetos desde la línea de comandos, útil para sembrar un bucket o subir un asset suelto sin escribir código:
wrangler r2 object put mi-bucket/logo.png --file=./logo.png --content-type=image/png
R2 ofrece dos clases por objeto. Standard, para lo que se lee a menudo, e Infrequent Access, más barata de guardar pero con un pequeño coste de recuperación, pensada para lo frío —backups, archivos que casi nunca se tocan—. Eliges la clase al escribir, y es una palanca económica: pagas menos por almacenar lo que rara vez lees, a cambio de unos céntimos por gigabyte cuando lo rescatas.
Por defecto, wrangler dev no toca tu bucket real: las operaciones de R2 se ejecutan contra un almacén local en tu máquina, así que desarrollas sin ensuciar producción ni pagar operaciones. Cuando quieras probar contra el bucket de verdad, marcas el binding como remoto y las llamadas salen a R2. Local por defecto, remoto a propósito.
El egress: el peaje que R2 no cobra
Aquí está el corazón del asunto. En la nube clásica guardar datos es barato, pero sacarlos cuesta: cada gigabyte que abandona el centro de datos hacia internet se factura como egress. Ese peaje, minúsculo por gigabyte, se vuelve enorme a escala, y —lo decisivo— crea gravedad. Cuantos más datos acumulas, más caro es moverlos a otra parte, así que te quedas donde estás. El egress es el foso del castillo: entrar en una nube es fácil y gratis, salir es caro por diseño.
R2 elimina el cargo de egress por completo. Te factura por dos ejes —lo que almacenas, en gigabyte-mes, y las operaciones que ejecutas, escrituras de clase A y lecturas de clase B— pero servir esos bytes al planeta no añade coste por transferencia. Para una carga de lectura intensiva —servir imágenes, vídeo, ser el origen de una CDN— el egress es justo el sumando que domina la factura de S3, y es exactamente el que R2 pone a cero.
Conviene poner cifras. El almacenamiento se cobra por gigabyte-mes; las escrituras son operaciones de clase A y las lecturas, de clase B, unas diez veces más baratas. Hay un nivel gratuito holgado —diez gigabytes-mes de almacenamiento, un millón de operaciones de clase A y diez millones de clase B cada mes— y, por encima, precios pequeños por unidad. Pero la columna que en otras nubes se comía el margen de servir contenido, el egress, aquí sencillamente no aparece.
Un ejemplo lo aterriza. Imagina diez terabytes de imágenes servidos cinco veces al mes: cincuenta terabytes de salida. En una nube con peaje, ese egress puede sumar miles al mes, y crece con cada visita nueva; en R2 esa salida cuesta exactamente cero, y tu factura solo refleja los diez terabytes guardados y las lecturas ejecutadas. El coste deja de escalar con la popularidad, que es precisamente lo que castigaba el modelo anterior.
flowchart LR App1[tu app] --> Nube[nube clasica] --> Peaje[factura por GB de salida] --> Net1[internet] App2[tu app] --> R2[R2] --> Cero[egress cero] --> Net2[internet] style Peaje fill:#f38ba8,color:#11111b style Cero fill:#a6e3a1,color:#11111b
Bucket y clave
Un bucket es un espacio plano de claves. Cada clave, una cadena, apunta a un objeto: bytes opacos más metadatos. Sin carpetas reales, sin edición parcial.
La API de S3
R2 implementa la interfaz de S3. Tus SDK y herramientas funcionan cambiando solo el endpoint y las credenciales: compatibilidad como vía de escape.
Egress cero
Sacar los datos hacia internet no cuesta. Se desmonta el peaje que domina la factura de servir medios y que ataba tus datos a un proveedor.
Dos ejes de coste
Pagas por almacenamiento y por operaciones, no por transferencia. El coste sigue a lo que guardas y tocas, no a cuánto descarga el mundo.
La palabra que hay que interiorizar es gravedad de los datos. Durante quince años, la arquitectura de la nube giró en torno a una asimetría casi gravitacional: la ingesta era barata o gratis, pero la salida costaba, y ese diferencial no era un accidente contable sino un mecanismo de retención. Los datos, una vez posados en un proveedor, se volvían pesados: moverlos a otro sitio —a otra nube, a tu propio centro, a un motor de análisis externo— exigía pagar el egress de todo el volumen, y cuanto más crecía tu almacén, más te ataba. La consecuencia estratégica era profunda: los datos atraen al cómputo. Ponías el análisis, la IA y las aplicaciones junto a los datos, no porque fuera lo óptimo, sino porque llevarse los datos donde estaba el cómputo era prohibitivo. El egress era el imán, y todo lo demás orbitaba a su alrededor. R2 apaga ese imán. Al cobrar solo por almacenar y por operar, y nada por transferir, disuelve la gravedad que mantenía cautivos a los bytes. El efecto no es que la nube salga un poco más barata; es que una decisión que antes estaba congelada —dónde viven tus datos y qué es libre de leerlos— vuelve a estar sobre la mesa. Puedes servir tu bucket como origen de una CDN sin que cada visita erosione el margen; puedes dejar que un motor de datos externo lo consulte sin pagar peaje por cada barrido; puedes plantearte multi-nube en serio, porque salir dejó de ser una condena económica. El ingeniero que entiende esto deja de preguntarse cuánto le cuesta guardar un terabyte —eso siempre fue barato— y empieza a preguntarse cuánto le cuesta que el mundo lo lea, porque ahí es donde el modelo clásico escondía el verdadero precio y donde R2 cambió la regla del juego.
- Describe tres tipos de datos de una app tuya que pertenezcan a un almacén de objetos y no a una base de datos, y explica por qué: tamaño, inmutabilidad, número.
- Crea un bucket con
wrangler r2 bucket create, decláralo como bindingBUCKET, y escribe y lee un objeto de prueba desde un Worker. - Estima el egress mensual de servir esos bytes —por ejemplo, un catálogo de imágenes visto un millón de veces— y traduce ese volumen a lo que costaría en una nube con peaje de salida frente a los cero de R2.
- Explica con tus palabras por qué la ilusión de carpetas en un bucket es solo prefijos de clave, y qué gana el sistema al no tener directorios de verdad.
- Argumenta la frase “los datos atraen al cómputo” con un caso concreto, y describe qué decisión de arquitectura se descongela cuando el egress cae a cero.