Integrar almacenamiento de objetos en una aplicación serverless puede parecer complejo, pero con R2 de Cloudflare el proceso se simplifica enormemente. A lo largo de esta sesión se muestra cómo crear un bucket, configurar el binding en Wrangler y subir una imagen de avatar desde una aplicación real, todo aprovechando la capa gratuita.
¿Qué es R2 y por qué es compatible con S3?
R2 es el servicio de object storage de Cloudflare [1:52]. Funciona de manera análoga a Amazon S3, el producto estrella de AWS para almacenamiento de archivos. La ventaja principal es que R2 ofrece compatibilidad al 100 % con S3 [3:18], lo que significa que librerías como Boto3 de Python u otras interfaces diseñadas para S3 funcionan sin modificaciones contra R2.
Esto permite migraciones sencillas desde AWS y reutilización de herramientas existentes. Para acceder con esas herramientas externas se generan access keys y secret keys desde la sección Manage a nivel de cuenta [7:30], donde se puede configurar permisos como read-only, expiración e incluso restricción por IP.
¿Qué ofrece la capa gratuita de R2?
Antes de usar R2 es necesario registrar una tarjeta de crédito o cuenta de PayPal [1:58]. Cloudflare hace un cargo mínimo de validación, pero solo cobra cuando se exceden los límites gratuitos [2:42]:
- 10 GB de almacenamiento.
- Un millón de operaciones por mes.
Esto resulta más que suficiente para proyectos personales o las etapas iniciales de una startup.
¿Cómo se crea el bucket y se configura el binding?
El bucket se puede crear desde el dashboard de Cloudflare o mediante la línea de comandos [4:08]. Una vez creado, la configuración se refleja en el archivo wrangler.toml del backend, donde se define el binding con un nombre como upload_bucket [4:30]. Así es como el worker accede al almacenamiento.
También hay que ejecutar la migración pendiente que indica la especificación. En este caso se aplicó directamente en remoto desde la carpeta del backend con un solo comando [4:50].
¿Cómo funciona el modo remoto en desarrollo local?
Una propiedad interesante dentro de Wrangler es remote [8:10]. Cuando se activa, ciertas operaciones en local leen y escriben directamente contra los recursos que están en producción. Por ejemplo:
- La base de datos D1 se ejecuta en modo local.
- El bucket de R2 se ejecuta en modo remoto.
- Los demás servicios funcionan en local.
Esto resuelve un problema real: en proyectos con múltiples workers, bases de datos y servicios, es difícil tener todo orquestado localmente. El modo remoto mejora la experiencia de desarrollo (dev experience) al permitir interactuar con recursos reales sin desplegar [8:35].
¿Cómo se detecta el entorno para elegir entre fetch y service binding?
La especificación define una lógica basada en una variable de entorno [0:22]. Cuando la variable está definida, la aplicación usa fetch para que funcione en local. Cuando no lo está, se utiliza el service binding del worker de backend. Esto funciona porque la variable solo existe en build time para el SPA (lo que se ejecuta en el cliente), no en server render [0:42].
¿Qué ocurrió al subir la imagen de prueba?
Al probar la funcionalidad, la imagen se subió correctamente al bucket a la primera [9:35]. Se almacenó dentro de una carpeta llamada avatars, con un UID como nombre y formato PNG. Desde el dashboard se pudo verificar, descargar y confirmar que era la misma imagen [9:50].
¿Por qué usar un bucket separado para assets en producción?
En el frontend, los assets compilados se suben a un KV de Cloudflare. En entornos de alto tráfico, es preferible compilar esos assets en GitHub Actions y colocarlos en un bucket de R2 [6:25]. Esto evita problemas de mismatch durante el rolling update, donde el worker antiguo y el nuevo podrían apuntar a archivos diferentes, generando glitches para los usuarios.
Además, los buckets permiten configurar custom domains, políticas de CORS y notificaciones que disparan eventos a colas, habilitando arquitecturas orientadas a eventos [7:05].
Si ya experimentaste con R2, comparte en los comentarios cómo lo estás usando o cómo mejorarías la interfaz de este proyecto.