Elegir: Images y Stream frente a R2 con transformación propia
Las mismas fotos y los mismos vídeos se pueden servir de tres maneras distintas, y las tres son defendibles. Comparamos el almacén gestionado de Images y Stream contra el camino de R2 con transformación bajo demanda y contra construir la tubería entera a mano, midiendo lo que de verdad separa a las opciones: no el precio por unidad, sino el control sobre el ciclo de vida, el esfuerzo de mantenimiento, la forma de la factura y el coste real de cambiar de idea dentro de dos años. Terminamos con reglas de decisión concretas y con la disciplina que hace reversible cualquiera de ellas.
Este nivel termina con la pregunta que de verdad se hace en una reunión de arquitectura, y que no tiene una respuesta única. Tienes fotos de productos, o vídeos de clases, o adjuntos de usuarios, y tres caminos abiertos: el almacén gestionado que guarda, transforma y sirve; tu propio bucket con transformación bajo demanda en el borde; o la tubería completa hecha a mano. Las tres funcionan y las tres se despliegan hoy. Lo que las separa no es el precio por unidad —esa comparación casi siempre es engañosa— sino cuatro cosas que se miden peor: cuánto control conservas sobre el ciclo de vida de tus bytes, cuánto esfuerzo humano recurrente compras o evitas, qué forma tiene la factura cuando el producto crece, y cuánto cuesta cambiar de idea dentro de dos años.
- Enumerar las tres arquitecturas posibles para servir medios y qué asume cada una.
- Comparar control, esfuerzo de mantenimiento y portabilidad con criterios explícitos.
- Distinguir las tres formas de factura y saber qué variable dispara cada una.
- Aplicar reglas de decisión concretas y dejar cualquier elección reversible.
Tres caminos para el mismo byte
Conviene empezar aclarando qué se está eligiendo, porque la pregunta suele plantearse mal. No estás eligiendo dónde guardar bytes —eso es la parte fácil y barata de las tres opciones— sino quién se hace cargo de las tres funciones que hacen falta para que un medio llegue bien: derivar las versiones que cada cliente necesita, ponerlas cerca de él y mantener todo eso vivo cuando algo se rompe. Las tres arquitecturas reparten esas funciones de forma distinta, y ahí está toda la diferencia.
El primer camino es el almacén gestionado. Subes el original a Images o a Stream, guardas un identificador en tu base de datos y sirves por una URL de entrega. Ellos poseen el original, la escalera de derivadas, la caché y la entrega. Tu código se reduce a emitir enlaces y a reaccionar a webhooks. Es lo que hemos visto en las cuatro lecciones anteriores.
El segundo camino es R2 con transformación bajo demanda. Los originales viven en tu bucket, con tus claves, tu jerarquía de prefijos y tus reglas de ciclo de vida. Un Worker delante decide el preajuste, invoca el motor de optimización sobre la marcha y devuelve el resultado, que se cachea en el edge. No hay proceso por lotes, no hay derivadas almacenadas y no hay migración de nada: solo un original y una función. Para vídeo existe el equivalente parcial en las transformaciones de medios, que recortan, redimensionan, extraen fotogramas o separan la pista de audio de un fichero que ya tienes.
El tercer camino es la tubería propia: bucket, cola de trabajos, procesos de codificación, almacén de derivadas, empaquetado, CDN y reproductor. Es el que se elegía por defecto hace diez años y hoy solo se justifica en dos situaciones muy concretas —volumen extremo donde el margen unitario compensa la nómina, o requisitos que ninguna plataforma cubre, como un códec exótico, una jurisdicción cerrada o un cifrado de extremo a extremo—.
Conviene precisar qué cubre y qué no el camino intermedio para vídeo, porque es donde más se equivoca la gente. Las transformaciones de medios operan sobre un fichero que ya tienes y producen recortes optimizados, fotogramas sueltos, tiras de miniaturas o solo la pista de audio, y se invocan por URL o desde un binding que alcanza incluso un bucket privado. Eso resuelve el clip de producto, la vista previa animada, la miniatura de portada y la extracción de audio para transcribir con un modelo. Lo que no hace es sustituir una escalera adaptativa completa para una película de dos horas: para eso está Stream, y confundir ambas cosas lleva a descubrir el problema tarde.
const original = await env.BUCKET.get("clips/a-142.mp4");
const clip = env.MEDIA.input(original.body)
.transform({ width: 480, height: 270 })
.output({ mode: "video", duration: "5s" });
return clip.response();
flowchart TD
Q1{es video de larga duracion}
Q1 -->|si| Q2{el video es el producto}
Q2 -->|no| S[Stream gestionado]
Q2 -->|si| T[tuberia propia o hibrido]
Q1 -->|no| Q3{ya tienes bucket propio}
Q3 -->|si| R[R2 mas transformacion]
Q3 -->|no| I[Images gestionado]La combinación más frecuente en producción no aparece en ningún diagrama de decisión: originales en R2 por portabilidad, transformación bajo demanda para la web, y Stream solo para las piezas de vídeo largo. Elegir por tipo de medio en vez de por proveedor es casi siempre mejor que buscar una única respuesta para todo el catálogo.
La comparación honesta
Puestas una al lado de otra, las diferencias dejan de ser cuestión de gusto. Vale la pena leer la tabla por columnas y no por filas: cada camino es coherente consigo mismo y responde a una prioridad distinta.
| Criterio | Gestionado | R2 con transformación | Tubería propia |
|---|---|---|---|
| Quién posee el original | El proveedor | Tú, en tu bucket | Tú |
| Nombre del recurso | Identificador opaco | Tu clave | tu jerarquía | Tu clave |
| Ciclo de vida y purga | Por API del proveedor | Reglas del bucket | clases de acceso | Tuyo por completo |
| Esfuerzo inicial | Horas | Un día | un Worker | Trimestres |
| Mantenimiento recurrente | Ninguno | Bajo | un Worker que cambia poco | Alto | equipo dedicado |
| Portabilidad | Baja | hay que reexportar | Alta | los bytes ya son tuyos | Total |
| Techo de control | El del producto | El del motor de transformación | Ninguno |
La fila del esfuerzo inicial merece una aclaración, porque es la que más se subestima en las dos direcciones. Poner en pie el camino intermedio no son horas de teclear: es un Worker que valida preajustes, resuelve claves, fija cabeceras de caché y decide qué hacer cuando el original no existe. Pero tampoco es un proyecto, porque ese Worker no crece con el catálogo ni con el tráfico, y una vez escrito cambia dos veces al año. Esa es exactamente la firma de una buena pieza de infraestructura: coste inicial acotado y coste marginal nulo.
Hay dos filas que suelen decidir la discusión y que conviene no leer por encima. La del nombre del recurso, porque un identificador opaco que solo existe dentro del proveedor es la forma más silenciosa de dependencia: tu base de datos acaba llena de claves que no significan nada fuera de ahí, y migrar exige reescribir cada referencia además de mover cada byte. Y la del ciclo de vida, porque las políticas de archivado, de clase de acceso barata y de borrado por retención son mucho más expresivas cuando el bucket es tuyo.
En la dirección contraria empuja una realidad incómoda: el camino gestionado no tiene mantenimiento porque no tiene piezas tuyas. Cada componente que añades a una tubería propia es un sitio donde puede fallar algo un domingo, y ese coste no aparece en ninguna hoja de cálculo hasta que se cobra en atención humana.
Hay un tercer eje que la tabla no captura bien y que decide muchas discusiones de cumplimiento normativo: dónde puede vivir el byte y quién puede tocarlo. Con bucket propio eliges región, política de retención, cifrado con tus claves y un registro de accesos que tú controlas, y puedes responder con precisión a una petición de borrado. Con el almacén gestionado dispones de las herramientas que el producto ofrezca, que son razonables pero no arbitrarias. Si tu sector te obliga a demostrar dónde está cada copia de un fichero, esa fila pesa más que todas las demás juntas.
Y conviene desconfiar de un argumento que aparece siempre y casi nunca resiste el análisis: el de que la tubería propia sale más barata porque el almacenamiento es barato. El almacenamiento es la línea trivial en cualquiera de las tres opciones. Lo que cuesta es el cómputo de codificación, la caché que hace que ese cómputo no se repita, y sobre todo la gente que decide qué hacer cuando el sistema se comporta de una forma que nadie previó.
Tres facturas con formas distintas
Comparar precios por unidad lleva a conclusiones falsas porque las tres opciones facturan variables diferentes, y lo que importa es cuál de esas variables crece en tu producto. Poner los tres modelos en la misma unidad es imposible; lo que sí se puede hacer es identificar, en cada uno, la magnitud que se multiplica cuando el negocio va bien.
El gestionado de imágenes cuenta originales almacenados, imágenes entregadas y transformaciones únicas. Crece con el número de piezas y con el número de peticiones, no con el peso. El gestionado de vídeo cuenta minutos almacenados y minutos entregados: crece con la duración del catálogo y con el consumo agregado de los espectadores, y es indiferente al tamaño del fichero y a la resolución. R2 con transformación cuenta gigabytes almacenados, operaciones de lectura y escritura, y transformaciones únicas, sin peaje de salida: crece con el volumen de bytes guardados y con la variedad de recetas, no con la popularidad. La tubería propia cuenta almacenamiento de todas las derivadas, cómputo de codificación y el salario de quien la sostiene.
Fíjate en la asimetría más útil de todo el nivel: en el camino del bucket propio, la popularidad es gratis, porque no hay peaje de salida y la caché absorbe las repeticiones. En el gestionado de imágenes y en el de vídeo, la popularidad es precisamente lo que se factura. Eso significa que un catálogo enorme y tranquilo y un catálogo pequeño y viral empujan hacia lados opuestos, y que la pregunta correcta no es cuánto contenido tienes sino cuántas veces se pide cada pieza.
Dos consecuencias prácticas se deducen de ahí. La primera: para un catálogo de imágenes muy grande y poco visitado, R2 con transformación suele ganar por goleada, porque el coste sigue a los bytes guardados y no a un contador de imágenes entregadas. La segunda: para un catálogo pequeño y muy visitado, o para cualquier cosa con vídeo largo, el gestionado suele ganar, porque el coste de ingeniería que evita es enorme comparado con la diferencia unitaria.
Un ejemplo aterriza la aritmética mejor que cualquier tabla de precios. Toma cien mil imágenes de producto de unos cinco megabytes cada una, servidas en cinco tamaños, con dos millones de vistas de página al mes y diez imágenes por página. En el gestionado pagas cien mil originales almacenados y veinte millones de imágenes entregadas, y la línea de entrega domina el total. En R2 con transformación pagas medio terabyte guardado, un contador de operaciones muy pequeño porque el edge cachea casi todo, y quinientas mil transformaciones únicas el primer mes que se reducen a casi nada en los siguientes; la salida no se factura. La diferencia entre los dos no es un porcentaje: es un orden de magnitud, y va en la dirección que casi nadie predice de memoria.
Advertencia sobre ese cálculo: úsalo como método, no como resultado. Los precios cambian, los planes se reorganizan y cualquier cifra concreta que memorices caducará antes que la estructura. Lo que no caduca es el procedimiento —identifica la variable que domina, proyéctala a tu escala real, y solo entonces mira la tarifa vigente—.
Invierte ahora las cifras —mil imágenes, cinco tamaños, cincuenta mil vistas al mes— y el resultado se da la vuelta: la factura del gestionado cabe en unos pocos euros y el ahorro que ofrece el bucket propio no paga ni la primera tarde de trabajo. La lección no es que un camino sea mejor, sino que la forma de tu catálogo decide cuál lo es, y esa forma es un dato que tienes y casi nunca miras antes de elegir.
En las dos opciones que usan el motor de optimización, lo que se factura no es cuántas imágenes tienes sino cuántas combinaciones distintas de origen y parámetros pides al mes. Un catálogo con cinco preajustes fijos es predecible; el mismo catálogo con anchos derivados del tamaño de la ventana del visitante puede multiplicar el contador por cien y hundir la tasa de acierto de la caché a la vez. La cardinalidad es la variable de coste, no el volumen.
Cómo decidir y cómo dejar la puerta abierta
Con todo lo anterior, las reglas de decisión se pueden escribir en pocas líneas. Si el medio es vídeo de larga duración y el vídeo no es tu producto sino un vehículo para venderlo, usa el gestionado sin más deliberación: la escalera de codificación, el empaquetado y el reproductor adaptativo son un proyecto que no quieres. Si son imágenes y ya tienes un bucket, quédate en el bucket y pon transformación delante: cuesta un Worker y conservas los nombres, el ciclo de vida y la salida. Si son imágenes y no tienes nada montado, el gestionado te pone en producción esta tarde y siempre puedes salir después. Y si vas a construir la tubería entera, que sea porque el vídeo o la imagen son el núcleo de tu ventaja competitiva, no porque el precio por gigabyte parezca alto.
Hay dos reglas menores que evitan errores frecuentes. La primera: no elijas por el pico que quizá alcances dentro de tres años, porque la opción que aguanta ese pico hipotético suele ser la que te impide llegar a él. La segunda: si dudas entre gestionado y bucket propio para imágenes, mira el cociente entre vistas y piezas del catálogo, que es la única cifra que separa de verdad los dos regímenes de factura.
Queda la parte que casi nadie escribe y que vale más que la decisión misma: cómo hacerla reversible. Tres disciplinas bastan. La primera es conservar siempre una copia del original en un almacén tuyo, aunque sirvas desde el gestionado; el coste de guardar es pequeño y es lo que convierte una migración en un cambio de configuración. La segunda es no dejar que el identificador del proveedor sea la clave de tu dominio: guarda tu propia clave estable y una correspondencia hacia la del proveedor, para que cambiar de proveedor no exija tocar cada referencia de tu base de datos. Y la tercera es no filtrar la URL del proveedor al cliente: sirve todo bajo tu dominio con un Worker delante, y el día que cambies de plataforma la aplicación no se enterará.
Esa tercera disciplina cuesta muy poco y es la que más devuelve. Una capa de indirección de unas pocas líneas convierte la elección de proveedor en un detalle de implementación, y de paso te da un sitio donde aplicar autorización, medir uso real por pieza y fijar cabeceras de caché propias.
const clave = new URL(request.url).pathname.slice(1);
const destino = await resolverProveedor(clave, env);
return fetch(destino, { cf: { cacheEverything: true } });
Con imágenes, conservar el original en tu bucket es trivial. Con vídeo, el máster suele ser el fichero que subió el creador y que ya no está en ninguna parte. Si tu catálogo tiene valor a largo plazo, activa la descarga en fichero de las piezas importantes y guarda esa copia en R2, o pídele al creador que suba a tu bucket y desde ahí ingesta a Stream. Sin máster, cambiar de plataforma no es una migración: es volver a producir.
Aplicadas desde el primer día, esas tres costumbres cuestan una tarde. Aplicadas cuando ya hay medio millón de referencias en la base de datos y la URL del proveedor está incrustada en aplicaciones móviles publicadas, cuestan un trimestre y una versión que no puedes forzar a actualizar. Es el ejemplo más limpio de una deuda que no se nota mientras no la necesitas y que se vuelve impagable justo el día que la necesitas.
Decide por medio
Imágenes y vídeo largo tienen economías distintas. Elegir un proveedor único para todo el catálogo suele ser peor que elegir dos.
Guarda el original
Una copia en tu bucket convierte cualquier migración futura en un reproceso, no en un rescate. Es el seguro más barato del sistema.
Tu clave, no la suya
Un identificador opaco esparcido por tu base de datos es la dependencia que no se ve hasta que intentas salir.
Tu dominio delante
Si el cliente nunca ve la URL del proveedor, cambiar de proveedor es un despliegue y no una migración de clientes.
Aquí se cierra el nivel con la idea que gobierna todas las anteriores, y que se aplica mucho más allá de los medios. Toda decisión de comprar frente a construir se presenta como una comparación de precios, y esa presentación es siempre una trampa, porque el precio es la única variable de la ecuación que se puede medir hoy y por eso acapara la conversación entera. Lo que de verdad se está decidiendo es otra cosa: dónde va a vivir la complejidad que el problema tiene y que no se puede eliminar. Servir medios bien exige transcodificar, negociar formatos, cachear, invalidar, purgar, medir y sostener todo eso cuando falla; esa complejidad existe la elijas donde la elijas, y lo único que puedes decidir es si vive dentro de tu organización, donde la pagas en atención y en calendario y a cambio la controlas, o fuera de ella, donde la pagas en factura y en dependencia y a cambio deja de ocupar espacio en la cabeza de tu equipo. Formulada así, la pregunta correcta no es cuánto cuesta cada opción, sino cuál es el conjunto pequeño de problemas en los que tu organización quiere ser excelente, porque cada problema que traes dentro compite por la misma atención finita que ese conjunto necesita. Un equipo que construye su propia tubería de vídeo para un producto de formación no está ahorrando dinero: está gastando su recurso más escaso —la capacidad de razonar sobre un sistema— en un problema que ya está resuelto y que ningún cliente suyo va a valorar. Y al revés, un equipo cuyo producto es el vídeo y que externaliza la codificación entera se ha quedado sin la única palanca con la que podría diferenciarse. El error simétrico existe y es igual de común. Ahora bien, esta lógica solo es sana si la decisión se mantiene reversible, y ahí está la disciplina que convierte una apuesta en una elección: guardar el original en un sitio que sea tuyo, nombrar los recursos con tus propias claves y no dejar que el dominio del proveedor llegue al navegador. Con esas tres costumbres, cualquiera de los tres caminos se puede abandonar en una tarde; sin ellas, incluso el camino correcto se convierte en una condena, porque lo que te ata a un proveedor nunca es su tecnología, sino la cantidad de decisiones tuyas que dejaste que él tomara por ti.
- Coge un catálogo real tuyo y calcula las tres facturas: gestionado, R2 con transformación y tubería propia. Incluye en la tercera una estimación honesta de horas de ingeniería al mes.
- Identifica qué variable dispara el coste en cada opción y qué pasa si esa variable se multiplica por diez. Di cuál de los tres modelos aguanta mejor tu crecimiento previsible.
- Cuenta cuántas combinaciones distintas de parámetros genera hoy tu interfaz. Si son más de una docena, redúcelas a un puñado de preajustes y vuelve a estimar.
- Audita tu base de datos: busca identificadores opacos de proveedor usados como clave de dominio y diseña la tabla de correspondencia que te faltaría para migrar.
- Pon tu propio dominio delante de los medios que sirves y comprueba que ninguna URL de proveedor llega al navegador. Describe qué migración te acabas de ahorrar.