Saltar a contenido

Capítulo 12. Cloudflare R2

Almacenamiento de objetos moderno, escalable y sin costos de salida

Objetivo

El objetivo de este capítulo es que el lector comprenda qué es Cloudflare R2, cómo funciona el almacenamiento de objetos y de qué manera puede diseñar una arquitectura profesional para guardar archivos de forma segura, escalable y económicamente predecible. Cloudflare presenta R2 como una solución de object storage escalable y rentable para aplicaciones cloud-native, contenido web y data lakes, destacando como rasgo central la ausencia de egress fees para la transferencia de datos hacia Internet.[web:57][page:2]

Al finalizar el capítulo, el lector será capaz de crear buckets, subir y descargar objetos, integrar R2 con Cloudflare Workers y Pages, diseñar estrategias de organización por prefijos, gestionar acceso público y privado, y comprender cuándo R2 es una alternativa especialmente atractiva frente a Amazon S3, Google Cloud Storage, Firebase Storage, Azure Blob Storage o Backblaze B2.[web:56][web:51][page:2]

¿Qué aprenderás?

Este capítulo enseña cuatro capacidades esenciales. La primera es conceptual: entender qué significa almacenamiento de objetos y por qué no debe confundirse con un sistema de archivos tradicional ni con una base de datos. La segunda es arquitectónica: comprender el papel de buckets, keys, metadata, permisos, URLs firmadas y bindings con Workers.[web:58][web:49][page:1]

La tercera es práctica: crear un bucket, conectarlo con código y usarlo para guardar imágenes, PDFs y otros archivos reales. La cuarta es estratégica: analizar costos, rendimiento, seguridad y casos de uso para tomar decisiones de infraestructura con criterio, especialmente en proyectos educativos, institucionales y de software moderno distribuido.[page:2][page:1][web:48]

Introducción

Imagina un archivo físico de una institución. En una oficina guardas credenciales impresas, en otra fotografías, en otra constancias PDF, en otra videos y en otra respaldos administrativos. Si todo eso se almacenara como archivos sueltos dentro de un solo equipo local o en un hosting improvisado, tarde o temprano aparecerían problemas: rutas desordenadas, copias inconsistentes, permisos confusos, poca escalabilidad, altos costos de transferencia y una dependencia peligrosa de un único servidor.

El almacenamiento de objetos nació para resolver ese tipo de problema a escala moderna. En lugar de pensar en discos y carpetas como un usuario de escritorio, se piensa en objetos identificados por claves, organizados dentro de buckets, acompañados por metadatos y accesibles mediante APIs. Cloudflare R2 toma ese modelo y le añade dos atributos especialmente llamativos para arquitecturas web: compatibilidad con la API de Amazon S3 y salida sin costo de egress directo desde R2.[web:51][web:57][page:2]

Dicho de forma sencilla, R2 es una gran bodega distribuida para archivos no estructurados. Pero no es una bodega caótica: cada objeto tiene una identidad, un camino lógico, metadatos, políticas de acceso y una forma consistente de ser leído o escrito por aplicaciones. Una vez se comprende esto, el almacenamiento deja de ser “una carpeta en el servidor” y se convierte en una capa arquitectónica formal.

¿Qué es Cloudflare R2?

Cloudflare R2 es el servicio de almacenamiento de objetos de Cloudflare. La documentación oficial lo describe como una solución rentable y escalable para grandes volúmenes de datos no estructurados, diseñada para aplicaciones cloud-native, contenido web y data lakes, y remarca que evita las costosas tarifas de egress asociadas con otros servicios típicos de cloud storage.[web:57][page:2]

En términos de arquitectura, R2 cumple el papel de capa de almacenamiento binario y documental. No es una base de datos relacional, no es un sistema de archivos montado como un disco local y no es simplemente “un folder remoto”. Es object storage: cada archivo se trata como un objeto identificado por una key y administrado mediante APIs.[web:58][web:49]

Historia

R2 aparece dentro de la evolución natural del ecosistema de Cloudflare. La compañía ya operaba una red global enfocada en CDN, DNS, seguridad, proxy inverso, Workers y distribución de contenido. Faltaba una pieza importante: un almacenamiento de objetos profundamente integrado con esa red y alineado con la filosofía edge. R2 llena ese vacío proporcionando un servicio de almacenamiento pensado para convivir con Workers, Pages y las capacidades de distribución de Cloudflare.[web:57][web:56]

Entender ese origen es importante porque explica por qué R2 no se presenta como un producto aislado. Su valor aumenta precisamente cuando se usa como parte de una arquitectura mayor dentro del ecosistema Cloudflare. No es casualidad que la documentación oficial destaque integraciones con Workers, presigned URLs, buckets públicos y APIs S3 compatibles.[web:56][web:53][web:51]

Filosofía

La filosofía de R2 puede resumirse en tres ideas: object storage para workloads modernos, compatibilidad con estándares de facto del ecosistema y economía centrada en eliminar fricción por salida de datos. Cloudflare insiste en dos mensajes repetidos: escala, costo predecible y ausencia de egress fees para transferir datos desde R2 directamente a Internet.[web:57][page:2]

Esa filosofía cambia la conversación arquitectónica. En muchos proveedores, el costo no está solo en guardar archivos, sino en servirlos. Eso distorsiona decisiones de diseño: algunas organizaciones conservan archivos donde no deberían, o evitan mover cargas por temor a pagar salida. R2 intenta reducir esa fricción y facilitar arquitecturas donde almacenar y servir contenido no quede penalizado por el simple hecho de leerlo desde fuera.[page:2][web:48]

Object Storage

R2 es object storage. Eso significa que los datos se guardan como objetos, cada uno con contenido y metadatos, dentro de un bucket. Amazon S3 define un objeto justamente como datos junto con su metadata descriptiva, y esa idea es central para comprender no solo S3 sino todo el paradigma de almacenamiento de objetos compatible con su ecosistema.[web:58][web:49]

El enfoque es ideal para imágenes, PDFs, respaldos, videos, documentos exportados, resultados de generación de IA, archivos institucionales, recursos estáticos y cualquier volumen grande de datos no estructurados. No es el lugar natural para hacer consultas complejas por relaciones como si fuera SQL; para eso existen otras piezas como D1 o una base de datos equivalente.

Compatibilidad con Amazon S3

Cloudflare documenta explícitamente una API compatible con S3 para interactuar con buckets y objetos en R2.[web:51] Esto es una ventaja enorme porque reduce fricción de migración, permite usar SDKs conocidos y hace posible integrar herramientas que ya hablan el lenguaje operativo del ecosistema S3.

La compatibilidad no significa identidad absoluta en todos los detalles. Significa que R2 implementa una capa S3-compatible suficientemente poderosa para trabajar con endpoints, SDKs y flujos habituales del mundo S3, incluyendo presigned URLs y clientes S3. Esa decisión de diseño convierte a R2 en un servicio mucho más fácil de adoptar por equipos que ya usan Amazon S3 o herramientas compatibles.[web:51][web:53]

Objetivos del servicio

R2 persigue varios objetivos prácticos: almacenar grandes volúmenes de datos no estructurados, reducir costos asociados al serving de archivos, integrarse con Workers y ofrecer una ruta de entrada amigable para usuarios del ecosistema S3. Cloudflare lo presenta como una solución para contenido web, aplicaciones cloud-native y data lakes, lo que muestra que no se limita a servir imágenes de un sitio; aspira a cubrir capas serias de almacenamiento dentro de arquitecturas modernas.[web:57]

Casos de uso

Los casos de uso naturales de R2 incluyen activos web, repositorios documentales, imágenes institucionales, credenciales digitales, respaldos, videos, PDFs, exportaciones de reportes, archivos generados por sistemas de IA y cualquier carga donde object storage sea un mejor modelo que un disco local o un folder dentro del servidor.[web:57][web:56]

¿Qué problema resuelve?

R2 resuelve varios problemas a la vez, y conviene analizarlos por separado para no caer en explicaciones simplistas. No se trata solo de “guardar archivos en la nube”. Se trata de superar limitaciones operativas, económicas y arquitectónicas del almacenamiento improvisado o excesivamente acoplado a servidores tradicionales.

Almacenamiento tradicional

En muchas aplicaciones pequeñas o medianas, el almacenamiento empieza mal: se guardan archivos directamente en el disco del servidor, en un hosting compartido, en carpetas accesibles por FTP o en rutas locales del proyecto. Eso suele funcionar al inicio, pero se vuelve frágil cuando el sistema crece, se replica, se balancea o necesita más seguridad.

El problema principal es el acoplamiento. Si las fotografías de alumnos, constancias PDF y respaldos viven dentro del mismo servidor que ejecuta la aplicación, mover o escalar la app se vuelve más difícil. El almacenamiento deja de ser una capa independiente y empieza a ser un detalle accidental del servidor que había disponible aquel día.

Servidores de archivos

Otra respuesta clásica ha sido montar servidores de archivos dedicados o shares de red. Esto mejora respecto a tener todo en el mismo directorio de la app, pero sigue exigiendo administración, permisos, mantenimiento, backups y alta disponibilidad a un nivel que muchas organizaciones no quieren ni deberían sostener por cuenta propia.

R2 elimina la necesidad de empezar por ahí. En lugar de administrar una máquina como repositorio de binarios, te apoyas en un servicio de object storage gestionado y accesible por API. La diferencia es grande: ya no administras “el servidor de archivos”; administras buckets, claves y políticas.

Costos de salida (Egress)

Este es uno de los problemas más distintivos que R2 intenta resolver. Cloudflare afirma que no cobra egress bandwidth fees para la transferencia de datos desde R2 hacia Internet, y esa ausencia de cargos de salida aparece como una de las características centrales del producto.[web:57][page:2]

En la práctica, el egress puede castigar arquitecturas donde leer archivos es parte normal del negocio: galerías, PDFs descargables, recursos estáticos, imágenes institucionales, backups externos o video delivery. Cuando servir datos cuesta demasiado, la arquitectura se deforma por razones contables. R2 busca precisamente suavizar ese problema.

Escalabilidad

Object storage está pensado para grandes volúmenes y para patrones donde el número de archivos crece con el tiempo. Cloudflare describe R2 como escalable, y la propia naturaleza del object storage evita parte del sufrimiento asociado a jerarquías locales de carpetas o discos individuales.[web:57]

Esto no significa que desaparezcan todas las decisiones de diseño. Hay que pensar en naming, prefijos, metadatos, permisos y flujos de acceso. Pero la plataforma está diseñada para crecer mejor que una carpeta compartida montada sobre un servidor improvisado.

Disponibilidad

R2 también resuelve parte del problema de disponibilidad al integrarse en una plataforma cloud gestionada. No convierte automáticamente cualquier arquitectura en inmortal, pero sí evita que la disponibilidad de tus archivos dependa de un único servidor doméstico, un hosting heredado o una máquina virtual con poca tolerancia al fallo.

Además, cuando R2 se combina con Workers, Pages o buckets públicos, la entrega de archivos puede integrarse de forma más natural con la red de Cloudflare, acercando almacenamiento y distribución dentro de una misma familia de servicios.[web:56][web:53]

Comparación: almacenamiento tradicional vs R2

Aspecto Almacenamiento tradicional Cloudflare R2
Unidad mental Archivo en disco o carpeta Objeto dentro de un bucket [web:58][web:49]
Administración Alta, depende de servidor y filesystem Gestionada por la plataforma
Escalabilidad Limitada por discos, rutas y operación Pensada para object storage escalable [web:57]
Acceso FTP, SMB, rutas locales, HTTP improvisado Workers API, S3 API, presigned URLs, buckets públicos [web:56][web:51][web:53]
Metadatos A menudo pobres o externos Integrados en el objeto [web:49][web:58]
Egress Puede ser costoso según proveedor Sin egress fees directos desde R2 [web:48]
Integración con edge Generalmente indirecta Natural con Workers y servicios Cloudflare [web:56]
Desacoplamiento de la app Bajo o medio Alto

Arquitectura de R2

La forma más clara de entender R2 es seguir el flujo completo de una operación real. Un usuario solicita un archivo o envía uno nuevo. La petición entra por la red de Cloudflare, puede pasar por un Worker que autentica, valida o transforma, y ese Worker lee o escribe un objeto dentro de un bucket R2. Finalmente se devuelve una respuesta, que puede ser el propio archivo, una URL firmada, metadatos o una confirmación JSON.[page:1][web:56][web:53]

Diagrama ASCII: arquitectura general de R2

[Usuario]
    |
    v
[Cloudflare Edge]
    |
    v
[Worker]
    |
    v
[R2 Bucket]
    |
    v
[Objeto]
    |
    v
[Respuesta]

Usuario

El usuario puede ser una persona descargando una constancia, un navegador subiendo una fotografía, una app móvil consultando un documento o un backend generando un PDF. Desde su punto de vista, solo hace una solicitud HTTP o interactúa con una URL firmada.

Cloudflare Edge

La petición entra al edge de Cloudflare, donde puede ser atendida por un Worker, un bucket público o una combinación de servicios. Esta capa es especialmente importante cuando el acceso no debe ser completamente público, porque ahí se pueden aplicar validaciones, límites, autenticación y reglas de negocio antes de tocar el almacenamiento.

Worker

El Worker actúa como mediador inteligente. Puede recibir un archivo, cambiar su nombre lógico, agregar metadata, verificar un token, definir el Content-Type, guardar el objeto en R2 y devolver un JSON con confirmación. También puede recuperar un objeto existente y devolverlo al cliente o generar una presigned URL para acceso temporal.[page:1][web:53][web:56]

Bucket

El bucket es el contenedor lógico donde viven los objetos. No es una carpeta del sistema operativo, aunque a primera vista pueda recordarla. Es una unidad de organización y política dentro del servicio R2.[page:1]

Objeto

El objeto es la pieza real de almacenamiento. Amazon S3 define un objeto como datos y metadata descriptiva, y ese modelo es completamente pertinente para R2. Un PDF, una imagen JPG, un video MP4 o un archivo JSON pueden ser objetos mientras estén identificados por una key dentro del bucket.[web:58][web:49]

Respuesta

La respuesta puede adoptar muchas formas: el archivo en sí, solo sus metadatos, una confirmación de escritura, una URL firmada, un redirect o una respuesta JSON con información del recurso. Esa flexibilidad es una de las razones por las que R2 funciona tan bien junto a Workers.

¿Qué es el almacenamiento de objetos?

Una vez vista la arquitectura, conviene definir el paradigma. Muchos errores de diseño provienen de usar object storage como si fuera un disco remoto o una base de datos incompleta. No es ninguna de las dos cosas.

Archivo

Un archivo es la unidad con la que piensa el usuario final: una foto, un PDF, un video, una hoja de cálculo. En el mundo de object storage, ese archivo se encapsula como un objeto almacenado bajo una key.

Objeto

Amazon S3 define un objeto como datos y metadata descriptiva.[web:58] Esa definición es excelente porque desmonta la idea simplista de que el almacenamiento solo guarda bytes. Un objeto también guarda contexto: tipo de contenido, control de caché, codificación, lenguaje, metadata de usuario y otros atributos posibles.[web:49][web:52]

Bucket

Un bucket es el contenedor lógico que agrupa objetos. Cloudflare dice claramente que un bucket almacena tus objetos en R2.[page:1] No es una unidad física visible para ti, sino una unidad organizativa y administrativa del servicio.

Metadatos

Los metadatos son datos sobre los datos. Amazon S3 documenta campos como Content-Type, Content-Encoding, Cache-Control, Content-Disposition y UserMetadata, mostrando que un objeto no solo tiene contenido, sino también atributos que modifican cómo debe tratarse o entregarse.[web:49][web:52]

Clave (Key)

La key es el identificador del objeto dentro del bucket. Amazon la describe como el nombre asignado al objeto y usada para recuperarlo.[web:58] En la práctica, esa key suele parecer una ruta, por ejemplo credenciales/2026/alumnos/000123/foto.jpg, aunque técnicamente no sea una ruta de filesystem sino una cadena lógica que el servicio interpreta como identificador.

Namespace

En términos prácticos, un bucket funciona como un namespace donde las keys deben ser únicas. Dos objetos distintos no pueden ocupar exactamente la misma key dentro del mismo bucket al mismo tiempo. Pensar en buckets como namespaces ayuda a diseñar estructuras limpias y a evitar colisiones.

Diferencias entre sistema de archivos, base de datos y almacenamiento de objetos

Modelo Qué almacena mejor Cómo se organiza Cuándo usarlo
Sistema de archivos Archivos locales ligados a una máquina Directorios reales y permisos del OS Apps pequeñas o trabajo local
Base de datos Datos estructurados y consultables Tablas, índices, relaciones Metadata, usuarios, permisos, negocio
Object Storage Archivos y blobs no estructurados Buckets + keys + metadata Imágenes, PDFs, videos, respaldos, assets [web:58][web:49][page:1]

La lección más importante es esta: una fotografía de alumno no debería vivir solo como fila SQL, y su metadata tampoco debería quedar enterrada únicamente dentro del object storage. Lo más profesional suele ser combinar ambos mundos: R2 para el archivo binario y D1 u otra base relacional para metadata, relaciones y consultas.

Buckets

Qué son

Un bucket es el contenedor lógico donde R2 almacena objetos. Cloudflare lo define de forma directa: un bucket guarda tus objetos en R2.[page:1] En arquitectura, el bucket es el primer nivel de separación entre distintos conjuntos de archivos.

Cómo funcionan

El bucket organiza objetos por keys y concentra configuración relevante como CORS, políticas de acceso público o privado y, según el caso, reglas de ciclo de vida. No debería entenderse como “una carpeta grande”, sino como una unidad administrativa con identidad propia.

Buenas prácticas

  • Separar buckets por grandes dominios de responsabilidad cuando tenga sentido.
  • Evitar crear demasiados buckets sin razón arquitectónica.
  • Mantener convenciones claras de naming.
  • Centralizar políticas coherentes de acceso y CORS.[web:50]
  • Diseñar pensando en lifecycle y evolución, no solo en el primer upload.

Organización

Una buena organización suele usar un bucket por tipo principal de carga o por política claramente distinta de acceso. Por ejemplo: institucional-publico, credenciales-privado, respaldos-app, videos-publicos. No se trata de multiplicar buckets arbitrariamente, sino de separar lo que realmente requiere reglas distintas.

Nombres

Los nombres deberían ser estables, descriptivos y legibles. Un bucket llamado bucket-final-v2-bueno-ahora-si es una mala señal. En cambio, capd-credenciales-privado o elprofe-documentos-publicos expresan finalidad y contexto.

Permisos

Los permisos importan desde el diseño. No todo bucket debe ser público. De hecho, un error frecuente es publicar demasiado temprano. R2 ofrece caminos distintos: acceso por Worker, buckets públicos y presigned URLs, cada uno con implicaciones de seguridad diferentes.[web:53][page:1]

Objetos

Cómo se almacenan

Cada objeto se guarda dentro de un bucket asociado a una key. El sistema no necesita que el archivo viva en una jerarquía real del sistema operativo. Basta con su identificador lógico, su contenido y sus metadatos.

Claves

La key es uno de los diseños más importantes del sistema de almacenamiento. Una mala key complica limpieza, migración, cacheo, control de acceso y mantenimiento. Una buena key expresa orden. Ejemplo razonable:

credenciales/2026/institucion-17/alumnos/000045/foto-original.jpg

Esa key ya contiene semántica útil: tipo de recurso, año, institución, entidad y variante del archivo.

Versiones

Aunque no toda arquitectura necesita versionado explícito de objetos, pensar en versiones es una excelente práctica para activos sensibles o de alto valor. En lugar de sobrescribir sin rastro, puede ser preferible usar keys versionadas como constancia-v1.pdf, constancia-v2.pdf o incluir timestamps/IDs de versión en la key.

Metadatos

Los metadatos son esenciales para servir correctamente los objetos y para preservarlos con contexto. Amazon S3 documenta múltiples tipos de metadatos y atributos asociados a contenido, cacheo y user metadata.[web:49][web:52] Esto permite, por ejemplo, indicar Content-Type: application/pdf, agregar Cache-Control, o definir Content-Disposition para controlar si un archivo debe visualizarse o descargarse.

Tipos MIME

El tipo MIME define cómo debe interpretar el cliente el contenido. Si lo configuras mal, un PDF puede descargarse como binario extraño o una imagen puede servirse sin el tipo adecuado. Para una arquitectura profesional, asignar correctamente Content-Type es parte del almacenamiento bien diseñado, no un detalle opcional.

Compatibilidad con Amazon S3

La compatibilidad con S3 es uno de los grandes aceleradores de adopción de R2. Cloudflare ofrece una S3-compatible API para interactuar con buckets y objetos, lo que permite reutilizar herramientas, SDKs, flujos de migración y conocimiento operativo existente.[web:51]

API S3

La API S3 es el lenguaje práctico del object storage moderno. Cuando R2 habla esa API, muchas bibliotecas y clientes existentes pueden trabajar con él con cambios mínimos o moderados. Esto importa mucho para migraciones, automatización y ecosistemas de terceros.

Endpoints

R2 usa endpoints compatibles con el dominio S3 de Cloudflare, y Cloudflare explica que las presigned URLs funcionan con el dominio S3 API <ACCOUNT_ID>.r2.cloudflarestorage.com.[web:53] Esto es clave porque permite que herramientas y SDKs entiendan a dónde conectarse.

SDK

Cloudflare indica que para generar presigned URLs necesitas un SDK de AWS o un cliente S3 compatible con firma Signature Version 4.[web:53] En la práctica, eso significa que gran parte del tooling del mundo S3 se vuelve directamente útil en R2.

Migraciones

La compatibilidad con S3 reduce fricción para migrar desde Amazon S3 o desde servicios y herramientas ya construidos alrededor del estándar de facto de S3. No elimina toda la revisión, pero sí evita tener que reescribir toda la capa de acceso a objetos desde cero.[web:51][web:53]

Ventajas

  • Aprovecha SDKs y clientes conocidos.[web:51][web:53]
  • Facilita migraciones progresivas.[web:59]
  • Reduce curva de aprendizaje para equipos ya acostumbrados a S3.
  • Permite presigned URLs con patrones bien establecidos.[web:53]

Limitaciones

La compatibilidad con S3 no debe interpretarse como clon exacto en todos los rincones funcionales. Cloudflare documenta específicamente lo que soporta dentro de su API S3. Además, por ejemplo, las presigned URLs no funcionan con custom domains públicos, sino con el dominio S3 API de R2.[web:53]

Crear un Bucket

Cloudflare documenta un flujo claro para crear un bucket R2 desde Wrangler o desde el Dashboard.[page:1] Aprender este proceso es fundamental porque casi toda arquitectura con R2 parte de esta unidad básica.

Creación

Desde el Dashboard o Wrangler, el flujo general es:

  1. Entrar a la cuenta Cloudflare.
  2. Ir a R2.
  3. Crear un bucket con un nombre claro.
  4. Verificar que el bucket exista.[page:1]

Con Wrangler, el proceso forma parte del flujo de trabajo orientado a infraestructura como configuración y automatización. Desde el Dashboard, es más visual y conveniente para aprendizaje o configuración inicial.

Configuración

Después de crear el bucket, conviene decidir desde temprano si será público o privado, si necesitará CORS para acceso desde navegador y cómo se integrará con Workers o con la API S3. Estas decisiones afectan tanto seguridad como experiencia de integración.[web:50][web:53][page:1]

Ubicación

Para el lector de este libro, el punto importante no es obsesionarse con pensar en un “disco” físico, sino entender la ubicación como parte de una plataforma gestionada. R2 abstrae bastante de la administración física del almacenamiento, por lo que la decisión principal no suele ser el rack ni el datacenter exacto, sino el modelo de acceso y la arquitectura alrededor.

Acceso

El bucket puede ser accedido mediante Workers bindings, S3 API, presigned URLs o mecanismos públicos según el caso.[web:56][web:51][web:53] Elegir el acceso correcto es una decisión arquitectónica de primer nivel.

Eliminación

Eliminar un bucket no es una simple limpieza cosmética. Puede implicar pérdida total de objetos si no hubo respaldo ni migración. Por eso, antes de eliminar, conviene vaciar, verificar dependencias y confirmar que no existan Workers, dominios o flujos de negocio apuntando a ese bucket.

Subir archivos

R2 admite varios caminos para subir archivos, y cada uno es adecuado para escenarios distintos. Lo importante no es memorizar todas las interfaces, sino entender que el servicio puede participar en flujos manuales, automatizados o programáticos.

Panel Web

El Dashboard sirve para operaciones iniciales, pruebas, inspección y cargas manuales. Es cómodo para entender el modelo, revisar objetos y hacer pequeñas gestiones administrativas.

Wrangler

Wrangler es útil cuando el flujo forma parte de desarrollo o despliegue automatizado. En proyectos serios, automatizar el acceso y la integración suele ser mejor que depender exclusivamente del panel visual.

API

La API S3-compatible permite integraciones programáticas y automatizadas. Si un sistema externo debe subir archivos o una herramienta ya está diseñada para S3, esta vía suele ser la más natural.[web:51]

SDK

Los SDKs compatibles con S3 simplifican mucho el trabajo porque abstraen firma, endpoints y manejo de requests. Son especialmente útiles para scripts, backends y procesos automatizados.

Workers

Cloudflare documenta explícitamente el uso de Workers API para leer y escribir objetos cuando el bucket está enlazado a un Worker.[page:1] Esta es probablemente la vía más poderosa dentro del ecosistema Cloudflare porque combina validación, lógica de negocio y acceso al objeto en una sola capa edge.

Ejemplo funcional de escritura desde Worker:

export interface Env {
  ARCHIVOS: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== 'PUT') {
      return new Response('Method Not Allowed', { status: 405 });
    }

    const url = new URL(request.url);
    const key = url.pathname.replace(/^\//, '');

    if (!key) {
      return Response.json({ ok: false, error: 'missing_key' }, { status: 400 });
    }

    await env.ARCHIVOS.put(key, request.body, {
      httpMetadata: {
        contentType: request.headers.get('content-type') || 'application/octet-stream'
      }
    });

    return Response.json({ ok: true, key });
  }
};

S3 Client

También puedes usar un cliente S3 para subir objetos directamente a R2 mediante su endpoint compatible. Esto es especialmente útil en migraciones o integraciones con herramientas existentes.[web:51][web:53]

Descargar archivos

Leer un objeto parece trivial, pero en realidad hay varias estrategias de acceso, cada una con implicaciones distintas de seguridad, costo y experiencia de usuario.

URLs públicas

Los buckets públicos permiten servir archivos directamente por HTTP sin autenticación adicional. Son muy útiles para recursos estáticos, imágenes de páginas institucionales, assets públicos y documentos que realmente deben ser accesibles para cualquier visitante.[page:1][web:53]

URLs privadas

Cuando el objeto no debe ser público, conviene accederlo a través de Workers o mediante URLs firmadas temporales. En este modelo, el archivo no se expone libremente al mundo solo por conocer un path.

Signed URLs

Cloudflare documenta las presigned URLs como un concepto heredado del ecosistema S3 para otorgar acceso temporal a un objeto sin exponer credenciales API.[web:53] La URL contiene la firma y autoriza una operación específica sobre un recurso concreto durante un tiempo limitado.[web:53]

Autenticación

En acceso privado, la autenticación puede ocurrir antes de generar la URL firmada o directamente en un Worker que actúa como puerta de entrada. El patrón correcto depende del caso: una app autenticada puede pedir una signed URL, o bien el Worker puede transmitir el archivo después de validar al usuario.

Control de acceso

Cloudflare advierte que una presigned URL debe tratarse como bearer token, porque cualquiera que la tenga puede usarla hasta que expire.[web:53] Esa frase es crucial. Una signed URL no es seguridad mágica; es credencial temporal embebida en una URL. Debe generarse con expiraciones cortas y compartirse solo con destinatarios esperados.[web:53]

Integración con Workers

La integración entre R2 y Workers es una de las razones más fuertes para usar ambos servicios juntos. Cloudflare documenta claramente que, al enlazar un bucket a un Worker, se pueden leer y escribir objetos directamente usando la Workers API.[page:1]

Lectura

Ejemplo funcional:

export interface Env {
  ARCHIVOS: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const key = new URL(request.url).pathname.replace(/^\//, '');
    const object = await env.ARCHIVOS.get(key);

    if (!object) {
      return new Response('Not Found', { status: 404 });
    }

    const headers = new Headers();
    object.writeHttpMetadata(headers);
    headers.set('etag', object.httpEtag);

    return new Response(object.body, { headers });
  }
};

Escritura

La escritura desde Worker es ideal cuando necesitas validar autenticación, imponer naming, registrar metadata o normalizar uploads. Esa capa de control hace que el bucket no dependa de uploads arbitrarios desde el cliente.

Actualización

En object storage, actualizar suele equivaler a sobrescribir o sustituir el objeto bajo la misma key, o a guardar una nueva versión con otra key. El patrón correcto depende del grado de trazabilidad que necesites.

Eliminación

Eliminar objetos puede hacerse desde Worker o desde la API S3, pero debe tratarse con cuidado. En sistemas institucionales, borrar sin historial puede ser un error grave. Con frecuencia conviene registrar metadata en D1 antes de eliminar físicamente el objeto.

Streaming

La lectura en streaming es especialmente valiosa para archivos grandes. Workers permite devolver el cuerpo del objeto sin cargarlo entero en memoria, lo cual encaja muy bien con el modelo edge y con buenas prácticas de eficiencia.

Ejemplos

Worker de subida de PDF con prefijos

export interface Env {
  DOCUMENTOS: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== 'POST') {
      return new Response('Method Not Allowed', { status: 405 });
    }

    const form = await request.formData();
    const file = form.get('file');
    const userId = String(form.get('userId') || '').trim();

    if (!(file instanceof File) || !userId) {
      return Response.json({ ok: false, error: 'invalid_input' }, { status: 400 });
    }

    const key = `credenciales/${userId}/documentos/${Date.now()}-${file.name}`;

    await env.DOCUMENTOS.put(key, file.stream(), {
      httpMetadata: {
        contentType: file.type || 'application/pdf'
      },
      customMetadata: {
        userId,
        originalName: file.name
      }
    });

    return Response.json({ ok: true, key }, { status: 201 });
  }
};

Integración con Pages

Cloudflare Pages puede convivir con R2 para servir o referenciar recursos estáticos, documentos e imágenes. Cuando un sitio institucional necesita muchas imágenes, PDFs y recursos descargables, R2 puede asumir la capa de almacenamiento mientras Pages entrega la parte frontend.

Imágenes

R2 funciona muy bien para imágenes públicas de páginas institucionales o contenido editorial, especialmente si el acceso es sencillo y el naming está bien organizado.

Documentos

Los PDFs de convocatorias, reglamentos, constancias públicas o materiales descargables pueden vivir en R2 y ser enlazados desde Pages. Esto desacopla los documentos del build del sitio y permite actualizarlos independientemente del frontend.

Recursos estáticos

Cuando el proyecto tiene recursos estáticos muy numerosos o generados dinámicamente, R2 puede complementar a Pages como repositorio escalable de archivos.

Diagrama ASCII: Pages -> R2

[Usuario]
   |
   v
[Cloudflare Pages]
   |
   v
[Enlace o Worker intermedio]
   |
   v
[R2 Bucket]
   |
   v
[Imagen / PDF / recurso]

Integración con D1

R2 y D1 forman una pareja arquitectónica muy potente. R2 almacena el binario; D1 guarda metadatos, relaciones y consultas. Separar ambas responsabilidades suele producir sistemas más limpios que intentar meter toda la lógica documental solo en uno de los dos servicios.

Guardar metadatos

En D1 puedes guardar user ID, nombre original del archivo, tamaño, tipo MIME, fecha de subida, estado, versión, visibilidad, hash lógico o referencias de auditoría. Eso habilita búsquedas y paneles administrativos imposibles si solo dependes de la key del objeto.

Consultar archivos

D1 no guarda el binario, pero sí puede decirte qué objetos existen, a quién pertenecen, cuáles vencen pronto, cuáles están activos y qué metadata tienen. Después, el Worker usa esa información para recuperar el objeto desde R2.

Relación entre base de datos y almacenamiento

La arquitectura recomendable suele ser esta:

  1. El Worker recibe un upload.
  2. Guarda el objeto en R2.
  3. Registra metadata en D1.
  4. Devuelve un identificador o resultado JSON.

Y a la inversa, para descarga:

  1. El Worker consulta D1.
  2. Verifica permisos y estado.
  3. Recupera el objeto en R2.
  4. Devuelve el stream o una signed URL.

Seguridad

R2 no es seguro “por existir”. La seguridad surge del modelo de acceso que diseñes alrededor del bucket y sus objetos.

Permisos

Debes decidir qué buckets son privados, cuáles son públicos y quién puede operar sobre ellos. Las operaciones críticas como subida privada, eliminación o acceso a documentos sensibles no deberían quedar expuestas por defecto.

API Tokens

Cloudflare indica que para generar presigned URLs se requieren credenciales API de R2: Access Key ID y Secret Access Key.[web:53] Esas credenciales deben tratarse como secretos de alta sensibilidad.

Signed URLs

Las presigned URLs son una excelente solución para acceso temporal, pero deben usarse con cautela. Cloudflare recomienda tratarlas como bearer tokens y usar expiraciones cortas para operaciones sensibles.[web:53]

Buckets privados

Un bucket privado es la opción natural para fotografías de alumnos, credenciales, constancias personalizadas, expedientes, respaldos y archivos internos. En estos casos, el acceso debería pasar por Worker o signed URLs temporales.

Buckets públicos

Los buckets públicos son útiles cuando los archivos realmente son públicos: imágenes institucionales, logos, catálogos descargables abiertos o recursos estáticos de sitio. El error aparece cuando se usa un bucket público por comodidad para contenido que en realidad requiere control de acceso.

Buenas prácticas

  • Mantener privado todo lo que no sea explícitamente público.
  • Generar signed URLs de corta duración.[web:53]
  • Usar Workers para centralizar autenticación y autorización.[page:1]
  • No incrustar credenciales S3 en frontend.
  • Definir CORS solo cuando sea necesario y con reglas precisas.[web:50]
  • Guardar metadata sensible y trazabilidad en D1 u otra base adecuada.

Costos

R2 cobra por almacenamiento total y por dos clases de operaciones, además de algunas condiciones específicas para almacenamiento Infrequent Access. Cloudflare explica que el pricing se basa en almacenamiento, operaciones Clase A y Clase B, y que no hay cargos de egress bandwidth para ninguna clase de almacenamiento cuando los datos salen directamente desde R2.[page:2]

Almacenamiento

En Standard storage, el costo es de $0.015 por GB-mes. En Infrequent Access, el costo es de $0.01 por GB-mes, pero este modo añade costos de retrieval y una duración mínima de almacenamiento de 30 días.[page:2]

Operaciones Clase A

Cloudflare define las Class A operations como operaciones más caras que tienden a mutar estado. Incluyen, entre otras, PutObject, CopyObject, CreateMultipartUpload, UploadPart, ListObjects y ciertas configuraciones del bucket.[page:2]

Operaciones Clase B

Las Class B operations tienden a leer estado existente y abarcan GetObject, HeadObject y otras operaciones de lectura o inspección.[page:2]

Transferencias

Cloudflare aclara que la transferencia de salida directamente desde R2 mediante Workers API, S3 API o dominios r2.dev no incurre en cargos de egress.[page:2] Este detalle es probablemente el argumento económico más famoso de R2.

Egress

El egress directo es gratuito en R2, pero Cloudflare también advierte que si conectas otros servicios medidos a un bucket R2, esos otros servicios podrían cobrarte según su propio modelo.[page:2] Eso significa que “sin egress” no equivale a “arquitectura entera gratis”, sino a un alivio muy concreto en una capa crítica del costo.

Comparación con otros proveedores

Servicio Rasgo económico distintivo Observación arquitectónica
Cloudflare R2 Sin egress directo desde R2; Standard $0.015/GB-mes; Class A $4.50/M; Class B $0.36/M [page:2] Muy atractivo para servir archivos y para ecosistema Cloudflare
Amazon S3 Gran madurez del mercado y ecosistema Referencia dominante para compatibilidad API [web:51][web:49]
Google Cloud Storage Integración sólida con GCP Muy útil si toda la arquitectura vive en Google
Firebase Storage Muy cómodo en ecosistema Firebase Excelente DX, pero la arquitectura puede quedar más atada a Firebase
Azure Blob Storage Fuerte en ecosistemas Microsoft Atractivo para organizaciones ya alineadas con Azure
Backblaze B2 Conocido por pricing competitivo Alternativa interesante en ciertos perfiles de costo

No todos estos proveedores fueron investigados en detalle en esta iteración, así que el capítulo debe entender esta tabla como comparación orientativa de enfoque más que como auditoría exhaustiva de pricing. Para un análisis de producción, siempre conviene verificar la tabla de precios vigente de cada proveedor.

Rendimiento

El rendimiento en object storage depende de varios factores: cercanía al usuario, patrón de acceso, tamaño de objetos, integración con edge y calidad del diseño de la aplicación. Cloudflare presenta R2 como escalable y pensado para workloads modernos, pero el rendimiento final también depende de cómo accedes a él: directo, mediante Worker o por SDK.[web:57][page:1]

Latencia

La latencia no depende solo de “dónde está el archivo”, sino de cuántas capas intervienen. Un bucket público con acceso simple puede responder de forma muy directa. Un Worker que valida permisos, consulta D1 y luego recupera el objeto añade pasos, aunque esos pasos aporten seguridad y lógica de negocio.

Escalabilidad

La escalabilidad es una de las fortalezas del object storage frente a soluciones basadas en filesystem local. R2 está diseñado para almacenar grandes cantidades de datos no estructurados y para crecer mejor que un servidor de archivos artesanal.[web:57]

Replicación

Desde la perspectiva del usuario de la plataforma, R2 abstrae buena parte de la complejidad de replicación y durabilidad. La enseñanza clave aquí no es aprender cómo replica internamente la plataforma, sino entender que la responsabilidad operativa de persistencia y servicio no recae en el desarrollador del mismo modo que en un servidor de archivos propio.

Disponibilidad

La disponibilidad mejora cuando el almacenamiento deja de depender de una única máquina o de una ruta local del sistema. Además, la integración con el ecosistema Cloudflare facilita arquitecturas donde acceso, validación y serving viven bajo una misma plataforma.

Durabilidad

En object storage, la durabilidad es una promesa central: que los archivos permanezcan almacenados correctamente a lo largo del tiempo. Aunque en esta iteración no se consultó una cifra específica oficial de durabilidad para R2, el servicio se presenta como durable y escalable para producción de datos no estructurados.[web:59][web:57]

Optimización

Guardar archivos no basta. Una arquitectura profesional de almacenamiento también piensa en eficiencia, orden, lifecycle y limpieza.

Compresión

No siempre conviene comprimirlo todo manualmente, pero sí conviene almacenar formatos eficientes. Por ejemplo, imágenes en formatos adecuados, PDFs ya optimizados y assets preparados para web cuando aplique.

Versionado

El versionado lógico en keys evita pérdidas accidentales por sobrescritura y mejora auditoría. No hace falta usarlo para todo, pero sí para documentos críticos, credenciales, exportaciones y archivos sensibles.

Organización

La organización por prefijos es probablemente la práctica más rentable intelectualmente. Hace más fácil listar, depurar, migrar, limpiar y comprender el bucket.

Prefijos

Ejemplos útiles:

imagenes/institucionales/home/
credenciales/2026/alumnos/
pdf/constancias/2026/
respaldos/firestore/2026-06/
ia-elprofe/conversaciones/

Ciclo de vida

Cloudflare menciona object lifecycles como siguiente paso en la documentación de R2 Workers API.[page:1] Esto es importante porque permite automatizar eliminación o transición de objetos antiguos según políticas temporales, algo muy útil en respaldos, archivos temporales o artefactos generados.

Limpieza

La limpieza planificada evita buckets eternamente inflados con archivos huérfanos. Para lograrla bien, conviene registrar metadata en D1, definir lifecycle y diseñar prefijos que permitan borrados masivos por lotes lógicos.

Casos reales

Credenciales Digitales

R2 es excelente para almacenar fotografías, fondos, exportaciones PDF y activos asociados a credenciales digitales. La combinación con Workers permite proteger acceso y con D1 permite relacionar cada objeto con su usuario, generación, vigencia y estado. Para un sistema de credenciales, R2 ofrece una mezcla muy valiosa de costo, escalabilidad y desacoplamiento del servidor principal.[web:56][web:57]

Fotografías de alumnos

Las fotografías de alumnos son un caso clásico de object storage: muchas imágenes, crecimiento constante, acceso puntual, importancia de metadatos y necesidad frecuente de privacidad. Un bucket privado con keys por institución, generación y alumno es mucho más profesional que guardar archivos dentro del hosting de la app.

Documentos PDF

Los PDFs institucionales, constancias, reglamentos, reportes y credenciales exportadas encajan perfectamente en R2. Además, Content-Type correcto y Content-Disposition permiten servirlos o descargarlos de manera adecuada.[web:49][web:52]

Constancias

Las constancias suelen requerir acceso controlado, trazabilidad y permanencia. R2 sirve muy bien como almacén del archivo final, mientras D1 guarda metadatos como folio, usuario, fecha, tipo y estatus.

Videos

Los videos son un caso especialmente sensible al costo de salida en muchos proveedores. Por eso R2 resulta atractivo cuando el serving de contenido multimedia forma parte del sistema y no quieres que el costo de entregar archivos crezca de forma agresiva por egress.[web:57][page:2]

Imágenes de páginas institucionales

Para banners, galerías y recursos visuales públicos, R2 es una gran opción porque desacopla imágenes del build del sitio y permite administrarlas como activos independientes.

Repositorio documental

Un repositorio documental institucional puede almacenar manuales, lineamientos, reglamentos, actas, certificados y formatos descargables en R2, mientras una base relacional gestiona categorías, permisos y búsquedas.

Respaldos

Los respaldos son otro caso natural. Exportaciones, dumps, snapshots y archivos de recuperación pueden vivir en prefijos específicos de backup dentro de un bucket privado. Aquí lifecycle y naming claro son especialmente importantes.

IA El Profe

Sistemas de IA generan archivos: datasets, prompts exportados, respuestas largas, audios, PDFs y documentos transformados. R2 es muy útil como almacén de artefactos de IA, especialmente cuando esos resultados deben descargarse, compartirse o integrarse con Workers para pipelines posteriores.

Migración

Una virtud importante de R2 es que no obliga a comenzar desde cero. Puede integrarse y también recibir cargas migradas desde otros sistemas.

Desde Firebase Storage

La migración desde Firebase Storage suele consistir en tres tareas: exportar o leer los objetos existentes, definir una estrategia de keys equivalente o mejorada en R2, y recrear metadata o relaciones en D1 u otra base donde convenga. El mayor beneficio suele aparecer cuando se quiere desacoplar archivos del ecosistema Firebase o mejorar costos de serving.

Desde Amazon S3

Aquí la compatibilidad S3 juega a favor. R2 ofrece una API S3-compatible, lo que facilita el uso de herramientas y flujos ya adaptados al modelo de S3.[web:51] Cloudflare también promociona migración progresiva como parte del valor de R2.[web:59]

Desde Google Cloud Storage

El reto suele estar menos en el archivo y más en la política de acceso, metadata y naming. La migración correcta no es solo copiar bytes: es decidir cómo quedarán claves, buckets, permisos y referencias de aplicación.

Desde servidor FTP

Migrar desde FTP suele ser también una migración cultural. Significa dejar atrás el paradigma de “subir archivos a carpetas del servidor” y pasar a un modelo más formal basado en object storage, APIs y controles de acceso consistentes.

Desde hosting tradicional

Cuando los archivos viven dentro del hosting de la app, migrar a R2 suele producir beneficios inmediatos en desacoplamiento. La aplicación deja de cargar con el peso de servir y conservar binarios, y puede concentrarse en lógica de negocio mientras R2 asume la capa documental y multimedia.

Diagramas ASCII

Arquitectura R2

[Cliente]
   |
   v
[Cloudflare Edge]
   |
   v
[Worker / acceso público]
   |
   v
[R2 Bucket]
   |
   v
[Objeto]

Bucket

bucket: credenciales-privado
 ├── fotos/2026/alumnos/0001.jpg
 ├── fotos/2026/alumnos/0002.jpg
 ├── pdf/constancias/folio-1001.pdf
 └── respaldos/2026-06/export.json

Objeto

Objeto
 ├── Key: credenciales/2026/alumnos/0001/foto.jpg
 ├── Body: bytes del archivo
 ├── Content-Type: image/jpeg
 ├── Cache-Control: private, max-age=0
 └── Custom Metadata: { userId: 0001, campus: tonala }

Worker -> R2

[Request]
   |
   v
[Worker valida y decide]
   |
   v
[R2 get/put/delete]
   |
   v
[Response o stream]

Pages -> R2

[Browser] -> [Pages UI] -> [link/img/src] -> [R2]

Aplicación -> R2

[App web / móvil]
      |
      v
[Worker API]
      |
      v
[R2 Bucket]

Flujo de carga

Usuario sube archivo
      |
      v
Worker valida auth y tipo
      |
      v
Genera key y metadata
      |
      v
R2 put()
      |
      v
JSON de confirmación

Flujo de descarga

Usuario solicita archivo
      |
      v
Worker valida permiso
      |
      +--> genera signed URL
      |         o
      +--> recupera objeto con get()
      |
      v
Archivo / stream / redirect

Buenas prácticas

  • Diseñar keys legibles y estables.
  • Separar binario en R2 y metadata relacional en D1 cuando sea necesario.
  • Usar buckets privados por defecto para datos sensibles.
  • Asignar Content-Type correcto.[web:49][web:52]
  • Usar Workers para validar acceso antes de leer o escribir.[page:1]
  • Tratar las presigned URLs como credenciales temporales.[web:53]
  • Planificar lifecycle, limpieza y prefijos desde el inicio.[page:1]
  • No depender de nombres improvisados o sobrescrituras silenciosas.

Errores comunes

  • Usar R2 como si fuera una base de datos.
  • Diseñar keys desordenadas sin convenciones.
  • Hacer públicos buckets que deberían ser privados.
  • Confundir signed URL con protección absoluta.[web:53]
  • No guardar metadata crítica fuera del objeto.
  • No pensar en Content-Type y Content-Disposition.[web:49][web:52]
  • Subir archivos desde frontend con credenciales expuestas.
  • No planear limpieza de archivos huérfanos.

Curiosidades

Una curiosidad importante es que Cloudflare no cobra egress directo desde R2 incluso si el acceso ocurre por Workers API, S3 API o dominios r2.dev.[page:2] Esa decisión económica no es un detalle menor: cambia completamente el atractivo del servicio para activos descargables y sistemas con mucha lectura.

Otra curiosidad es que las presigned URLs de R2 siguen el modelo S3 y se generan del lado cliente o servidor con credenciales API y firma Signature Version 4, sin comunicación previa con R2 para crearlas.[web:53]

También es llamativo que Cloudflare recomiende sus propios bindings de Workers como alternativa más integrada para acceso del lado servidor, mostrando que R2 tiene dos almas complementarias: una compatible con el mundo S3 y otra profundamente nativa dentro del ecosistema Cloudflare.[web:53][page:1]

Resumen

Cloudflare R2 es el servicio de almacenamiento de objetos de Cloudflare, diseñado para guardar grandes volúmenes de datos no estructurados con compatibilidad S3 y sin tarifas de egress directo hacia Internet. Su verdadero valor aparece cuando se entiende como una capa arquitectónica, no como una simple carpeta remota.[web:57][web:51][page:2]

R2 resuelve problemas reales de desacoplamiento, escalabilidad y costos de serving de archivos. Se integra especialmente bien con Workers para acceso controlado y con D1 para metadata y relaciones, lo que permite construir arquitecturas limpias para imágenes, PDFs, credenciales, respaldos y artefactos de aplicaciones modernas.[page:1][web:56]

La clave para usarlo bien está en diseñar buckets con criterio, organizar keys por prefijos, manejar seguridad con buckets privados y URLs firmadas, y separar el almacenamiento binario de la lógica relacional de negocio. Cuando esas decisiones se toman correctamente, R2 deja de ser “dónde guardo archivos” y se convierte en una infraestructura documental profesional.[web:53][web:49][web:58]

Glosario

Bucket

Contenedor lógico donde R2 almacena objetos.[page:1]

Clase A

Operaciones de R2 más costosas y orientadas a mutación o administración, como PutObject o ListObjects.[page:2]

Clase B

Operaciones orientadas a lectura o inspección, como GetObject y HeadObject.[page:2]

Content-Type

Metadato que indica el tipo MIME del objeto, por ejemplo image/jpeg o application/pdf.[web:49][web:52]

Egress

Transferencia de datos de salida desde el servicio hacia Internet. En R2, el egress directo es gratuito.[page:2]

Key

Identificador del objeto dentro del bucket.[web:58]

Metadata

Información descriptiva asociada a un objeto, como tipo de contenido, control de caché o metadata personalizada.[web:49][web:52]

Namespace

Espacio lógico donde las keys deben ser únicas; en la práctica, el bucket cumple este papel.

Object Storage

Modelo de almacenamiento donde los archivos se guardan como objetos con datos y metadata, dentro de buckets.[web:58][web:49]

Presigned URL

URL firmada temporalmente que permite realizar una operación concreta sobre un objeto sin exponer credenciales API permanentes.[web:53]

R2Bucket

Binding de Workers usado para interactuar programáticamente con un bucket R2 desde el runtime de Cloudflare.[page:1]

S3-compatible API

API de R2 compatible con el modelo operativo de Amazon S3 para trabajar con buckets y objetos.[web:51]

Signed URL

Sinónimo práctico de presigned URL en el contexto de acceso temporal a objetos.[web:53]

20 preguntas de autoevaluación

  1. ¿Qué es Cloudflare R2 y qué problema principal intenta resolver?[web:57][page:2]
  2. ¿Por qué R2 no debe confundirse con un sistema de archivos tradicional?[web:58][web:49]
  3. ¿Qué significa que R2 sea object storage?
  4. ¿Qué es un bucket y qué papel cumple en la arquitectura?[page:1]
  5. ¿Qué diferencia hay entre un objeto y un archivo desde el punto de vista del usuario?
  6. ¿Qué función cumplen los metadatos de un objeto?[web:49][web:52]
  7. ¿Qué ventaja aporta la compatibilidad S3 de R2?[web:51]
  8. ¿Qué son las presigned URLs y por qué deben tratarse como bearer tokens?[web:53]
  9. ¿Cuándo conviene usar bucket público y cuándo bucket privado?[web:53]
  10. ¿Qué relación ideal existe entre R2 y D1 en una arquitectura profesional?
  11. ¿Qué ventaja económica importante ofrece R2 respecto al egress?[page:2]
  12. ¿Qué son las operaciones Clase A y Clase B?[page:2]
  13. ¿Por qué el diseño de keys es crítico para mantener orden y escalabilidad?
  14. ¿Cómo ayuda un Worker al acceso seguro a R2?[page:1]
  15. ¿Qué papel cumple Content-Type en la entrega correcta del archivo?[web:49][web:52]
  16. ¿Qué tipos de archivos encajan especialmente bien en R2?
  17. ¿Qué riesgos existen al usar signed URLs sin expiración corta?[web:53]
  18. ¿Por qué migrar desde un servidor FTP a R2 implica también un cambio cultural?
  19. ¿Cómo organizarías un bucket para almacenar fotografías y constancias de una institución?
  20. ¿Qué buenas prácticas reducen errores de seguridad, orden y costos en R2?[page:2][web:53][web:49]

Proyecto práctico

Este proyecto diseña e implementa un sistema profesional de almacenamiento documental y fotográfico usando Cloudflare R2, pensado para un sistema de credenciales digitales con decenas de miles de usuarios.

Objetivo del proyecto

Construir una arquitectura que permita:

  • Crear un bucket para archivos privados.
  • Configurar permisos y estrategia de acceso.
  • Subir imágenes y PDFs.
  • Organizar archivos por prefijos.
  • Integrar el bucket con Cloudflare Workers.
  • Publicar archivos temporales mediante signed URLs.
  • Combinar acceso público y privado según tipo de recurso.
  • Escalar a decenas de miles de usuarios con una convención coherente.
  • Analizar costos para aproximadamente 100,000 fotografías y 50,000 documentos PDF.

1. Diseño general

Arquitectura recomendada:

[Frontend / Admin / App móvil]
          |
          v
      [Worker API]
       /        \
      v          v
   [R2]        [D1]
  • R2 almacena el binario.
  • D1 guarda metadata, relaciones y permisos.
  • Workers valida autenticación, construye keys, sube objetos y entrega acceso controlado.

2. Crear un Bucket

Nombre sugerido:

credenciales-digitales-privado

Razón: expresa finalidad y nivel de acceso. No mezcla material público con fotografías o constancias privadas.

3. Configurar permisos

Estrategia recomendada:

  • Bucket principal privado.
  • Acceso de lectura y escritura solo por Worker binding o API S3 autenticada.
  • Signed URLs para descargas temporales puntuales.[web:53]
  • Bucket separado opcional para recursos públicos institucionales.

4. Organizar carpetas mediante prefijos

Prefijos sugeridos:

fotos/2026/institucion-001/alumnos/000001/perfil.jpg
fotos/2026/institucion-001/alumnos/000001/credencial.jpg
pdf/2026/institucion-001/constancias/folio-000001.pdf
pdf/2026/institucion-001/credenciales/folio-000001.pdf
logs-exports/2026/06/reporte-01.json

Esta estructura facilita búsquedas, limpieza, migración y separación por tipo de recurso.

5. Integrar R2 con Cloudflare Workers

wrangler.toml:

name = "credenciales-storage-api"
main = "src/index.ts"
compatibility_date = "2026-06-28"

[[r2_buckets]]
binding = "ARCHIVOS"
bucket_name = "credenciales-digitales-privado"

Cloudflare documenta precisamente el patrón de añadir un binding R2 al archivo de configuración de Wrangler y luego usarlo desde el Worker.[page:1]

6. Worker funcional para subir imágenes y PDFs

export interface Env {
  ARCHIVOS: R2Bucket;
}

function buildKey(kind: 'foto' | 'pdf', institutionId: string, userId: string, filename: string) {
  const year = new Date().getUTCFullYear();

  if (kind === 'foto') {
    return `fotos/${year}/institucion-${institutionId}/alumnos/${userId}/${filename}`;
  }

  return `pdf/${year}/institucion-${institutionId}/documentos/${userId}/${filename}`;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== 'POST') {
      return new Response('Method Not Allowed', { status: 405 });
    }

    const form = await request.formData();
    const file = form.get('file');
    const kind = String(form.get('kind') || '').trim();
    const institutionId = String(form.get('institutionId') || '').trim();
    const userId = String(form.get('userId') || '').trim();

    if (!(file instanceof File)) {
      return Response.json({ ok: false, error: 'missing_file' }, { status: 400 });
    }

    if (!['foto', 'pdf'].includes(kind) || !institutionId || !userId) {
      return Response.json({ ok: false, error: 'invalid_metadata' }, { status: 400 });
    }

    const key = buildKey(kind as 'foto' | 'pdf', institutionId, userId, file.name);

    await env.ARCHIVOS.put(key, file.stream(), {
      httpMetadata: {
        contentType: file.type || 'application/octet-stream'
      },
      customMetadata: {
        institutionId,
        userId,
        kind,
        originalName: file.name
      }
    });

    return Response.json({ ok: true, key }, { status: 201 });
  }
};

7. Publicar archivos mediante URLs firmadas

Cloudflare explica que las presigned URLs permiten GET, HEAD, PUT y DELETE, con expiraciones entre 1 segundo y 7 días, y que deben generarse usando credenciales API y Signature Version 4.[web:53]

Patrón recomendado:

  1. El usuario autenticado pide acceso a un archivo.
  2. El Worker valida permisos consultando D1.
  3. Si procede, el backend genera una presigned URL corta, por ejemplo 60 segundos.[web:53]
  4. El cliente usa esa URL para descargar directamente desde R2.

8. Acceso público y privado

Separación recomendada:

  • Público: logos, banners, imágenes institucionales, PDFs abiertos.
  • Privado: fotografías de alumnos, credenciales, constancias nominales, respaldos, documentos internos.

No mezclar ambos mundos en la misma política de acceso evita errores peligrosos de seguridad.

9. Estructura para decenas de miles de usuarios

Con decenas de miles de usuarios, la clave es consistencia. Un diseño razonable sería:

fotos/2026/institucion-001/alumnos/000001/perfil.jpg
fotos/2026/institucion-001/alumnos/000002/perfil.jpg
...
pdf/2026/institucion-001/constancias/folio-000001.pdf
pdf/2026/institucion-001/constancias/folio-000002.pdf

Complemento recomendado en D1:

  • user_id
  • institution_id
  • r2_key
  • mime_type
  • file_size
  • visibility
  • created_at
  • document_type
  • status

10. Análisis comparativo de costos

Supuesto del proyecto:

  • 100,000 fotografías.
  • 50,000 documentos PDF.
  • Se asume, para un cálculo base simple, que cada fotografía pesa 500 KB y cada PDF 300 KB.
  • Almacenamiento total aproximado:
  • Fotos: 100,000 × 500 KB = 50,000,000 KB ≈ 47.68 GB.
  • PDFs: 50,000 × 300 KB = 15,000,000 KB ≈ 14.31 GB.
  • Total ≈ 61.99 GB.

Con R2 Standard a $0.015/GB-mes, el almacenamiento mensual bruto estimado sería aproximadamente:

  • 61.99 × 0.015 = $0.93 USD/mes aprox., antes de operaciones y sin considerar el free tier.[page:2]

Además, R2 incluye 10 GB-mes gratis al mes, por lo que la cantidad facturable efectiva bajaría a aproximadamente 51.99 GB-mes:

  • 51.99 × 0.015 = $0.78 USD/mes aprox. de almacenamiento bruto facturable.[page:2]

Si el proyecto realiza 150,000 escrituras iniciales de objetos, seguiría dentro del millón de Class A gratuitas mensuales del free tier.[page:2] Si durante el mes recibe, por ejemplo, 2,000,000 descargas o lecturas GetObject, seguiría dentro de los 10 millones de Class B gratuitas mensuales.[page:2]

Desde el punto de vista estrictamente de almacenamiento y lectura moderada, R2 se ve extraordinariamente competitivo para este escenario, sobre todo porque el egress directo no añade costo.[page:2]

Frente a Firebase Storage, Amazon S3 y Google Cloud Storage

En esta iteración no se investigaron las tarifas oficiales actuales de Firebase Storage, Amazon S3 y Google Cloud Storage, por lo que no sería correcto inventar precios exactos. Sin embargo, sí puede establecerse una conclusión arquitectónica prudente: para un proyecto con decenas de miles de fotografías y documentos PDF, el modelo sin egress directo de R2 puede generar una ventaja económica significativa cuando el sistema sirve archivos frecuentemente al público o a usuarios autenticados.[page:2][web:57]

La comparación profesional real debería completarse verificando las tablas vigentes de cada proveedor para almacenamiento, operaciones y transferencia. Pero como criterio de diseño, R2 es especialmente atractivo cuando el costo de lectura y salida de archivos es una preocupación central.

11. Despliegue y pruebas

Flujo recomendado:

  1. Crear bucket desde Dashboard o Wrangler.[page:1]
  2. Vincular bucket en wrangler.toml.[page:1]
  3. Desarrollar Worker localmente.
  4. Probar uploads con formularios, Postman o curl.
  5. Verificar objetos en el Dashboard.
  6. Añadir generación de URLs firmadas para acceso privado.
  7. Registrar metadata en D1.

Ejemplo de prueba de upload con curl:

curl -X POST https://tu-worker.workers.dev/upload \
  -F "file=@./foto.jpg" \
  -F "kind=foto" \
  -F "institutionId=001" \
  -F "userId=000001"

12. Evolución futura

Este proyecto puede evolucionar de varias maneras:

  • Añadir D1 para metadata documental.
  • Incorporar lifecycle para limpieza automática de temporales.[page:1]
  • Usar presigned URLs de carga para que el cliente suba directo a R2 sin pasar todo el binario por el Worker.[web:53]
  • Integrar analytics de acceso por documento.
  • Separar buckets por política pública/privada.

Cierre conceptual del capítulo

Cloudflare R2 obliga a pensar el almacenamiento como una capa seria de la arquitectura, no como un apéndice improvisado del servidor. Ese cambio de mentalidad es tan importante como cualquier detalle técnico. Cuando las aplicaciones maduran, lo que más cuesta no es guardar un archivo, sino gobernarlo: nombrarlo bien, servirlo bien, protegerlo bien y pagarlo de forma sostenible.

R2 resulta especialmente valioso porque combina tres ideas difíciles de reunir en un mismo servicio: object storage moderno, compatibilidad práctica con el ecosistema S3 y un modelo económico muy competitivo para serving de archivos por su ausencia de egress directo. Para desarrolladores, docentes, instituciones y emprendedores que construyen plataformas reales, eso lo convierte en una pieza fundamental de la arquitectura web moderna.[web:51][page:2][web:57]