5 · Datos y almacenamientoLección 3 de 5
Object storage, data lakes y warehouses
Object storage, data lakes and warehouses
Dónde viven las fotos, los datasets, los pesos y los logs de un sistema de ML, cuánto cuesta guardarlos un año y cómo los encuentra después un analista o un job de entrenamiento.
Secciones14
- 01Object storage: objetos, llaves y buckets
- 02Bloques y archivos: los otros dos almacenes extra
- 03La URL prefirmada: un permiso de un rato, dentro de la dirección
- 04Durabilidad y clases de almacenamiento
- 05Ciclo de vida, retención y lo que cuesta
- 06Data lake y particiones por fecha
- 07Warehouse, lakehouse y snapshots
- 08Feature store y backfill extra
- 09Errores comunes
- 10En la vida real extra
- 11Ejercicios
- 12Lo que sigue
- 13Palabras que vas a oír
- 14Chequeo
C01 guarda millones de fotos, el dataset para reentrenar, los pesos del modelo y un log de cada predicción. ¿Dónde va cada cosa, cuánto cuesta guardarla un año y cómo la encuentra después quien la necesita?
Cada día, C01 recibe ≈ 10 millones de fotos, de ≈ 200 KB cada una: 10 M × 200 KB = 2 TB al día. Cada mes se reentrena con un dataset nuevo. Cada versión del modelo deja un archivo de pesos de ≈ 98 MB. Y cada predicción deja una línea de log (log: el registro de lo que pasó, como qué foto llegó, qué categoría salió y a qué hora) de ≈ 300 bytes: 10 M × 300 B = 3 GB al día.
Son cuatro cosas muy distintas. Unas son enormes y se leen poco; otras son chiquitas y se escriben millones de veces. Unas tienen que durar años; otras conviene borrarlas a los 90 días, porque traen datos de personas.
En la lección de formatos viste cómo se escribe cada archivo por dentro (json lines, parquet). En la de bases de datos, cómo se guardan filas que cambian. Aquí vas a ver dónde se guardan los archivos cuando son millones, quién puede entrar, qué pasa si se rompe un disco, cuánto cuesta y cómo se organizan para que un analista o un job de entrenamiento (un programa que arranca, hace su tarea y termina) lea un día sin tener que leer el año.
Object storage: objetos, llaves y buckets
EsencialObject storage: objects, keys and buckets
El disco de tu computadora guarda archivos en carpetas, con un sistema de archivos. Funciona muy bien para una máquina. Para 3,650 millones de fotos al año, que leen cientos de máquinas a la vez, se usa otra cosa: un object storage (almacenamiento de objetos).
Los más conocidos son de la nube, las computadoras que se rentan por hora o por GB: S3 (Simple Storage Service) de AWS, la nube de Amazon; Cloud Storage (GCS) de Google, y Blob Storage de Microsoft Azure. También hay versiones que una empresa instala en sus propias máquinas, como MinIO o Ceph.
Un objeto: bytes, llave y metadatos
Un objeto tiene tres partes:
- Los bytes: el contenido, sea un JPEG, un Parquet o un archivo de pesos. A S3 le da igual qué son.
- La llave (key): el nombre con el que lo guardas y lo pides, como
fotos/2026/11/06/ana-tenis.jpg. - Los metadatos (metadata): datos sobre el objeto, como su tamaño, su tipo (
image/jpeg), la fecha en que se guardó y una huella de su contenido.
No hay que instalar nada para usarlo: se le habla por HTTP, con los métodos que ya conoces. PUT guarda un objeto, GET lo lee, DELETE lo borra y HEAD lee solo sus metadatos. Además hay LIST, que lista llaves. Cada una de esas operaciones es una request, y se cobra aparte de los GB guardados.
Se reemplaza entero
Un objeto no se edita a la mitad. Para cambiar un byte de una foto, la bajas completa, la cambias y la vuelves a subir: un PUT a la misma llave reemplaza al objeto viejo entero. Tampoco se le agregan líneas al final, como a un log en tu disco. Sí se puede leer solo un pedazo, con el header Range de un GET («dame del byte 1,000 al 5,000»): así un lector de Parquet lee solo las columnas que necesita.
¿Por qué tan limitado? Porque esa sencillez es lo que lo deja crecer sin tope. Si nadie edita a la mitad, no hay que coordinar a dos máquinas que escriben el mismo archivo. Cada objeto es independiente, y S3 puede repartir billones de ellos entre miles de discos. A cambio, tú organizas tus datos en objetos que se escriben una vez y se leen muchas.
Si dos programas hacen PUT a la misma llave casi al mismo tiempo, no se mezclan: gana el último, entero, y el otro se pierde sin aviso. Si no quieres que nadie pise una llave, desde agosto de 2024 S3 acepta escrituras condicionales: con el header If-None-Match: * («solo si no hay nada con esa llave»), el PUT falla con el código 412 si la llave ya existe. Y un GET justo después de un PUT ya ve el objeto nuevo: S3 lo garantiza desde diciembre de 2020. Antes, al reemplazar un objeto, un GET podía devolver el viejo durante un rato, la consistencia eventual de la lección de bases de datos.
Para ir más hondoObjetos grandes: la subida en partes+
Un solo PUT sube hasta 5 GB. Para algo más grande, como un checkpoint de un LLM (los pesos guardados a mitad del entrenamiento), se usa la subida en partes (multipart upload): el archivo se corta en pedazos, por ejemplo de 100 MB, que suben en paralelo y se reintentan uno por uno si falla la red. Al final, una request le dice a S3 «junta las partes», y el objeto aparece completo de golpe. Antes de eso, nadie lo ve a medias. Se aceptan hasta 10,000 partes, y así un objeto llega a 50 TB (desde diciembre de 2025; antes, el tope era 5 TB).
El bucket
Los objetos viven dentro de un bucket. Ojo: en la lección de percentiles, un bucket era el intervalo de un histograma. Aquí es otra cosa, y en el glosario se llama bucket de objetos: el contenedor donde guardas objetos.
En S3, cada bucket tiene, por omisión, un nombre único en el mundo: si alguien ya usó ml-datos, tú no puedes (desde marzo de 2026 también se puede crear con un sufijo que lleva tu número de cuenta y la región, y ese nombre es solo tuyo). El bucket vive en una región, un grupo de centros de datos en un lugar, como el norte de Virginia, y lleva sus reglas: quién puede leer y escribir (su bucket policy), cuánto dura cada cosa y si guarda versiones viejas.
La dirección completa de un objeto junta las dos cosas: en s3://ml-datos/logs/dt=2026-11-06/part-0001.parquet, el bucket es ml-datos y la llave es todo lo que sigue.
Las carpetas no existen
La llave es solo un texto, de hasta 1,024 bytes, y puede llevar «/». La consola de S3 te enseña «carpetas», pero dentro hay una lista plana de llaves, ordenada. Lo que parece una carpeta es un prefijo (prefix): el principio que varias llaves comparten.
fotos/2026/11/06/.Esto tiene consecuencias. Listar con un prefijo es rápido, porque las llaves están ordenadas, y S3 te las da de 1,000 en 1,000. Pero «renombrar una carpeta» no existe: hay que copiar cada objeto a su llave nueva y borrar el viejo. Con un millón de objetos son dos millones de requests.
Para ir más hondoCuántas requests aguanta un prefijo+
El prefijo también reparte la carga. Según AWS, S3 aguanta al menos 3,500 escrituras y 5,500 lecturas por segundo por prefijo, y escala de a poco: mientras crece, puede responder 503 (Slow Down, «más despacio»), y el cliente reintenta. Los 500 GET por segundo del pico de C01 quedan lejos de ese techo.
El juguete de abajo es un object storage hecho con un diccionario de Python: las llaves son texto y no hay carpetas. Fíjate en cuántas requests cuesta cambiar un byte y mover dos fotos.
from collections import Counter
objetos, requests = {}, Counter() # un object storage de juguete: llave → bytes
def put(llave, datos):
requests["PUT"] += 1
objetos[llave] = bytes(datos) # si la llave ya existía, lo reemplaza entero
def get(llave):
requests["GET"] += 1
return objetos[llave]
def listar(prefijo):
requests["LIST"] += 1
return sorted(k for k in objetos if k.startswith(prefijo))
for llave, kb in (("fotos/2026/11/06/ana-tenis.jpg", 200), ("fotos/2026/11/06/beto-bici.jpg", 150),
("fotos/2026/11/07/caro-lampara.jpg", 180)):
put(llave, b"\xff" * kb * 1000)
print(listar("fotos/2026/11/06/"))
foto = bytearray(get("fotos/2026/11/06/ana-tenis.jpg")) # para cambiar un byte...
foto[10] = 0
put("fotos/2026/11/06/ana-tenis.jpg", foto) # ...se sube entera otra vez
for k in listar("fotos/2026/11/06/"): # «renombrar la carpeta» del día 6
put(k.replace("/06/", "/06-revisadas/"), get(k))
del objetos[k]; requests["DELETE"] += 1
print(listar("fotos/"))
print(dict(requests))['fotos/2026/11/06/ana-tenis.jpg', 'fotos/2026/11/06/beto-bici.jpg']
['fotos/2026/11/06-revisadas/ana-tenis.jpg', 'fotos/2026/11/06-revisadas/beto-bici.jpg', 'fotos/2026/11/07/caro-lampara.jpg']
{'PUT': 6, 'LIST': 3, 'GET': 3, 'DELETE': 2}Seis PUT para tres fotos guardadas: una para cambiar un byte y dos para «mover» dos fotos. En S3 de verdad, la copia se hace sin bajar los bytes (una request COPY), pero se cobra igual que un PUT.
Bloques y archivos: los otros dos almacenes
ExtraBlock and file storage: the other two
El object storage no es la única manera de guardar en la nube. Hay otras dos, y cada una se parece a algo que ya conoces.
Almacenamiento de bloques: un disco de red
Un disco, por dentro, es una fila larguísima de bloques numerados, pedazos de tamaño fijo. El sistema operativo pone encima su sistema de archivos y decide qué bloques forman cada archivo. Eso es el almacenamiento de bloques (block storage): te dan un disco en crudo, y tu máquina lo usa como suyo.
En AWS se llama EBS (Elastic Block Store). En la lección de memoria lo viste: es un disco que vive en otra parte del centro de datos, se conecta por la red y sobrevive si la máquina se apaga. El más común, gp3, da de base 3,000 operaciones por segundo (IOPS) y 125 MiB/s.
Lo bueno: puedes cambiar un byte a la mitad de un archivo, como en tu laptop, con latencias de milisegundos o menos. Por eso ahí van el disco con el que arranca la máquina y las bases de datos. Lo malo: normalmente lo usa una sola máquina a la vez, vive en una sola zona de disponibilidad (un centro de datos dentro de la región) y pagas los GB que reservas, los uses o no. Si reservas 500 GB y usas 50, pagas 500.
Algunas máquinas traen además un SSD conectado directo a ellas (instance store; casi siempre NVMe, la conexión más rápida para un SSD), todavía más rápido que EBS porque no pasa por la red. Pero es de esa máquina: si se apaga o se reemplaza, lo que tenía se pierde. Sirve como caché, para los pesos que se bajaron de S3, nunca como único lugar de algo.
Almacenamiento de archivos: una carpeta compartida
El tercero es una carpeta compartida por la red, que muchas máquinas montan a la vez y ven como un disco suyo. Habla NFS, un protocolo de los años ochenta para compartir archivos. En AWS se llama EFS (Elastic File System); en Google, Filestore. Tiene carpetas de verdad, renombrar es instantáneo y se puede editar a la mitad. Cuesta bastante más por GB.
| Bloques (EBS) | Archivos (EFS) | Objetos (S3) | |
|---|---|---|---|
| Cómo se ve | Un disco | Una carpeta compartida | Llaves y objetos, por HTTP |
| Quién lo usa a la vez | Una máquina | Muchas | Cualquiera con permiso |
| Editar a la mitad | Sí | Sí | No: se reemplaza entero |
| Latencia típica | Menos de 1 ms a pocos ms | ≈ 1 ms al leer, ≈ 3 ms al escribir | ≈ 100 a 200 ms por request, según AWS |
| Precio aproximado (us-east-1, 2026) | ≈ US$0.08 por GB-mes reservado (gp3) | ≈ US$0.30 por GB-mes (Standard) | ≈ US$0.023 por GB-mes (Standard) |
| En C01 | El disco de cada nodo | — | Fotos, logs, datasets y pesos |
Con 100 GB al mes: ≈ US$8 en EBS, ≈ US$30 en EFS y ≈ US$2.30 en S3. Por eso la regla de la Ronda (M13) es sencilla: lo que vive con una máquina va en su disco; lo que se comparte o tiene que durar va al object storage. C07, la búsqueda por foto, guarda sus vectores (embeddings) en un disco gp3 porque los lee el page cache de una sola máquina; C10, el chat con un LLM, baja sus pesos de S3 al disco local de cada máquina nueva.
La URL prefirmada: un permiso de un rato, dentro de la dirección
EsencialPresigned URLs: a short-lived permission inside the address
Ana toca «publicar», y la foto de 200 KB tiene que quedar guardada en un bucket del marketplace, para mostrarla en la publicación. La Ronda no dice cómo la sube la app: lo que sigue es el diseño más común, como supuesto, porque explica bien la idea. Hay dos caminos malos.
- Que pase por tu API. La foto cruza tu balanceador de carga y tus servidores solo para que ellos la vuelvan a subir a S3. A 500 fotos por segundo, eso son ≈ 100 MB/s de bytes que no necesitabas mover.
- Darle a la app las credenciales de S3, la clave secreta que da permiso de entrar al bucket. Cualquiera que abra la app podría sacarlas y leer o borrar todo el bucket. Nunca.
El camino bueno es una URL prefirmada (presigned URL; en Google se llama signed URL, URL firmada).
Quién firma, qué permite y cuánto dura
Tu servidor sí tiene permiso de escribir en el bucket. Con su clave secreta calcula una firma: un número que solo se puede producir con esa clave, y que depende de exactamente qué se permite (la cuenta se llama HMAC, y la verás en la lección de cifrado). Mete la firma en la dirección, en la query (la parte de la URL después del ?, en pares nombre=valor), y se la da a la app. Firmar es una cuenta local: el servidor no tiene que llamar a AWS.
La URL de una subida trae, entre otras, estas partes:
- El bucket y la llave:
c01-subidas.s3.amazonaws.comy/fotos/8f3a.jpg. X-Amz-Credential: quién firmó, sin su secreto. Puede ser un usuario o un rol (una identidad de AWS con sus permisos, que usa un programa en vez de una persona).X-Amz-DateyX-Amz-Expires=900: cuándo se firmó y cuántos segundos vale.X-Amz-Signature: la firma.
Cuando llega el PUT, S3 recalcula la firma. Si alguien cambió la llave, el método o la hora, no coincide y responde 403. Si coincide, revisa que no haya vencido y que quien firmó todavía tenga permiso de hacer eso. Como el permiso viaja en la URL, esa request no lleva header Authorization.
Lo que permite una URL prefirmada es una operación (un PUT o un GET) sobre una llave, durante un rato que elige quien firma: en este ejemplo, 15 minutos, igual que en C02 (las cámaras de los centros de distribución). En S3, como mucho 7 días, y menos si se firmó con credenciales temporales (las que caducan solas, como las de un rol), porque vence cuando ellas vencen.
Para ir más hondoLo que una firma puede amarrar, y lo que no+
Quien firma puede amarrar más cosas. En C02, la firma también cubre el tipo del archivo (Content-Type: video/mp4): si la «caja», la computadora del sitio conectada a las cámaras, manda otro, S3 lo rechaza. Lo que una URL de PUT no limita es un tamaño máximo (solo se puede firmar uno exacto); para eso hay otra variante, un formulario firmado (POST con una policy) que sí pone un máximo de bytes.
- App de Ana · la foto de 200 KB
La app tiene la foto, pero no tiene credenciales del bucket: si las tuviera, cualquiera podría sacarlas de la app y leer o borrar todo. Lo único que recibe es una URL prefirmada para una sola llave. - API del marketplace · firma la URL
Revisa que Ana inició sesión, inventa una llave nueva y firma con la clave secreta de su rol una URL dePUTque vale 15 minutos. Firmar es una cuenta local: no llama a S3. La API nunca ve los bytes de la foto. - Base de datos · la publicación y su llave
La publicación de Ana guarda el texto de la llave (fotos/8f3a.jpg), no la foto. Es una fila chiquita en una base de datos. - Bucket de fotos · privado · S3
Un bucket privado del producto. Recibe elPUT, recalcula la firma, revisa que no haya vencido y guarda el objeto con durabilidad de once nueves. Una regla de ciclo de vida lo mueve de clase cuando envejece. - Gateway de C01 · variante: la llave
En la variante que propone M13 para ahorrar, la request a C01 lleva la llave, no los bytes (en el diseño base, el gateway recibe la foto). El gateway lee la foto del bucket con el permiso de su propio rol, que solo deja leer el prefijo de fotos: unGETpor foto, ≈ 304 millones al mes. - Log en el lake · la llave, no la foto
El log de cada predicción anota la llave de la foto, la categoría y la confianza: ≈ 300 bytes. La foto ya vive en el bucket del producto; copiarla «por si acaso» serían ≈ 60 TB más cada mes.
Sirve igual para bajar. En la Ronda, M02 lo usa en los trabajos largos: el resultado (un JSON enorme, una máscara, un PDF) se guarda en el bucket, y el cliente lo baja con una URL prefirmada de GET que vence en minutos.
Durabilidad y clases de almacenamiento
EsencialDurability and storage classes
Guardaste la foto de Ana. ¿Qué tan seguro es que siga ahí dentro de un año?
Once nueves
La durabilidad (durability) es la probabilidad de que un objeto que guardaste siga ahí, intacto, después de un año. S3 está diseñado para 99.999999999 % al año: once nueves. Dicho al revés, la probabilidad de perder un objeto dado en un año es 0.000000001 %, es decir, 10⁻¹¹.
Es un número tan chico que conviene traducirlo a objetos.
DELETE equivocado se pierden muchas más.¿Cómo se logra? En S3 Standard (y en las demás clases de la tabla de abajo), cada objeto se guarda repartido en muchos discos, en al menos tres zonas de disponibilidad (centros de datos separados por kilómetros) de la región. Cada pedazo lleva una huella para detectar si un bit se dañó. Y cuando un disco muere, el sistema rehace sus pedazos con los demás antes de que muera otro.
Para ir más hondoPor qué tres copias dan tantos nueves+
Con números de juguete: un disco pierde sus datos con probabilidad 1 % al año, y una copia perdida se rehace en un día.
- Una copia: pierdes 1 de cada 100 objetos al año: 10⁻².
- Dos copias: para perder el objeto, la segunda tiene que morir el mismo día que la primera: 10⁻² × (10⁻² ÷ 365) ≈ 2.7 × 10⁻⁷.
- Tres copias: además, la tercera, ese mismo día: 10⁻² × (10⁻² ÷ 365)² ≈ 7.5 × 10⁻¹².
Ignorando factores de 2 o 3, eso ya son ≈ 11 nueves. Las copias tienen que fallar por separado: tres discos en el mismo estante, con la misma fuente de luz, no cuentan como tres (en la lección de probabilidad lo viste como falla correlacionada). S3 no guarda tres copias completas, sino pedazos con información extra (erasure coding), que dan la misma protección con menos bytes.
Durabilidad no es disponibilidad
En la lección de probabilidad viste la disponibilidad y los los nueves: qué fracción del tiempo un servicio contesta. Son cosas distintas:
- Disponibilidad: ¿S3 me responde ahora? S3 Standard está diseñado para 99.99 % (≈ 53 minutos al año en que una request puede fallar). En su contrato (el SLA), AWS promete menos: 99.9 % cada mes, y si no lo cumple devuelve una parte del cobro.
- Durabilidad: ¿mi objeto sigue existiendo? Once nueves.
Un bucket puede no contestar un rato sin perder nada: reintentas y ahí está. Y al revés, con disponibilidad perfecta, un DELETE tuyo borra la foto para siempre. La durabilidad te protege del hardware, no de ti. Para lo segundo hay versionado del bucket (cada PUT o DELETE guarda la versión anterior), Object Lock (una versión que nadie puede borrar antes de una fecha) y copias en otra cuenta o región.
Clases de almacenamiento
No todo se lee igual de seguido. La foto de una publicación activa se ve cientos de veces; la de una que se vendió hace un año, casi nunca. Por eso S3 tiene clases de almacenamiento (storage classes): la misma foto, con la misma durabilidad, guardada más barato a cambio de que leerla cueste más o tarde más. Los nombres son de S3: IA quiere decir Infrequent Access (acceso poco frecuente), y Glacier (glaciar) es la familia de las clases para archivo.
| Clase | Guardar, US$ por GB-mes | Leer | Mínimo que te cobran | Para qué |
|---|---|---|---|---|
| Standard | 0.023 | Al instante, sin cargo por GB | — | Lo que se lee seguido |
| Standard-IA | 0.0125 | Al instante, + US$0.01 por GB | 30 días y 128 KB por objeto | Se lee poco, pero hay que tenerlo a la mano |
| Glacier Instant Retrieval | 0.004 | Al instante, + US$0.03 por GB | 90 días y 128 KB por objeto | Se lee una vez por trimestre |
| Glacier Flexible Retrieval | 0.0036 | De minutos a horas | 90 días | Archivo que casi no se lee |
| Glacier Deep Archive | ≈ 0.001 | Hasta 12 h, o 48 h barato | 180 días | Lo que se guarda por ley |
Son precios de lista de la región del norte de Virginia (us-east-1), revisados en noviembre de 2026; cambian por región y con el tiempo. Standard baja un poco con volúmenes muy grandes: US$0.022 pasados los primeros 50 TB y US$0.021 pasados 500 TB.
Fíjate en la columna del mínimo. Si guardas algo en Standard-IA y lo borras a los 10 días, te cobran 30. Un objeto de 10 KB en Standard-IA paga como si pesara 128 KB. En Flexible Retrieval y Deep Archive, cada objeto paga además ≈ 40 KB de metadatos: con millones de objetos chicos, se nota. Y lo que se guarda en Glacier Deep Archive no se puede abrir al momento: primero pides que lo «restauren», y esperas horas. Google tiene la misma escalera con otros nombres: Standard, Nearline (30 días), Coldline (90) y Archive (365).
Elegir clase a mano para millones de objetos es imposible. Para eso existen las reglas de la sección siguiente.
Ciclo de vida, retención y lo que cuesta
EsencialLifecycle, retention and what it costs
Reglas de ciclo de vida
Una regla de ciclo de vida (lifecycle rule) le dice al bucket qué hacer con los objetos según su edad, sin que ningún programa tuyo lo haga. Tiene dos tipos de acción:
- Mover (transition): «a los 30 días, pasa a Glacier Instant Retrieval».
- Borrar (expiration): «a los 365 días, bórralo».
Cada regla aplica a un prefijo (o a los objetos con cierta etiqueta), así que distintas partes del bucket pueden tener reglas distintas. S3 la revisa por su cuenta, más o menos una vez al día. Así se ve una, en el JSON que recibe S3 (ilustración):
{"Rules": [{"ID": "fotos-viejas", "Status": "Enabled", "Filter": {"Prefix": "fotos/"},
"Transitions": [{"Days": 30, "StorageClass": "GLACIER_IR"}],
"Expiration": {"Days": 365}}]}Retención: cuánto guardar y por qué
Antes de escribir la regla hay que decidir la retención (retention): cuánto tiempo se conserva cada cosa. La deciden tres fuerzas, y casi siempre tiran en direcciones distintas.
- El costo. Cada GB se paga cada mes que sigue ahí. Lo que nunca se borra crece sin parar.
- La ley y la privacidad. Las fotos y los logs traen datos de personas: caras, placas, ubicaciones en el EXIF (los datos que la cámara esconde dentro del JPEG). Las leyes de datos personales piden guardar solo lo necesario y borrar cuando alguien lo pide. Cuanto más guardas, más puedes filtrar.
- El ML. Para reentrenar, buscar drift y comparar modelos de meses distintos hace falta historia.
En C01, la Ronda las reparte así: los logs de predicción duran 90 días; las copias de fotos que van a etiquetar, también 90; los agregados diarios (cuántas predicciones por categoría, por ejemplo) se guardan para siempre, porque no traen datos de nadie. El golden set (las fotos fijas, bien etiquetadas, con las que se examina cada modelo) y los snapshots de entrenamiento (la lista exacta de datos con que se entrenó cada modelo, en la sección 7) no caducan: si el golden set se borrara a los 90 días, ya no podrías comparar el modelo de marzo con el de octubre sobre las mismas fotos. Pero cuando alguien pide que borren su foto, se busca por su huella en todos ellos.
Lo que cuesta: GB-mes y requests
S3 cobra con dos medidores.
- GB-mes: guardar 1 GB durante un mes. En Standard, ≈ US$0.023. Guardar 2 GB durante medio mes también es 1 GB-mes.
- Requests: en Standard, US$0.005 por cada 1,000
PUT(yCOPYyLIST), y US$0.0004 por cada 1,000GET. LosDELETEson gratis. Cuando una regla mueve un objeto de clase, eso también es una request (una transición): US$0.01 por cada 1,000 objetos hacia Standard-IA, US$0.02 hacia Glacier Instant Retrieval y US$0.05 hacia Deep Archive.
Para pasar de días a meses, las cuentas usan 30.4 días por mes (365 ÷ 12).
Una equivalencia para recordar: un PUT cuesta lo mismo que guardar ≈ 217 KB durante un mes (0.000005 ÷ 0.023 GB). Con una foto de 200 KB, subirla cuesta como un mes de guardarla. Con un log de 300 bytes, subirlo cuesta como guardarlo 60 años.
Para ir más hondoEl descuento por volumen y los objetos chicos+
La cuenta usa US$0.023 para todo. Con el descuento por volumen, «todo en Standard» bajaría a ≈ US$15,900 y el ahorro, a ≈ 36 %: la conclusión no cambia. AWS conoce bien el problema de mover objetos chicos: desde septiembre de 2024, una regla nueva no mueve objetos de menos de 128 KB, a menos que se lo pidas.
Esa cuenta es la del bucket del producto, el del marketplace. C01 no guarda su propia copia de cada foto: la foto ya vive ahí, y C01 solo anota su llave. Si la copiara «por si acaso», la Ronda (M12) calcula ≈ 60 TB más cada mes: ≈ US$1,380 el primer mes, US$2,760 el segundo, y así cada mes más, con datos personales y sin dueño.
Las fotos entran cada día; las primeras semanas viven en Standard y después pasan a una clase fría hasta que se borran. Arranca con el bucket del marketplace: 10 millones de fotos de 200 KB, 30 días en Standard, Glacier Instant Retrieval y borrado al año. Las cuentas son de un mes cualquiera, cuando el bucket ya está lleno.
No cuenta lo que cuesta leer de la clase fría (US$0.01 a 0.03 por GB, u horas de espera en Glacier) ni las duraciones mínimas (si la retención es menor que el mínimo de la clase, te cobran el mínimo), ni los ≈ 40 KB de metadatos que paga cada objeto en Deep Archive. Standard se cobra a US$0.023 por GB-mes para todo, sin el descuento por volumen. Precios de lista de us-east-1, noviembre de 2026.
Prueba Deep Archive (precio 0.001, mover 0.05): sale más caro que dejar todo en Standard. Después pon la retención en 90 días: «Todo en Standard» baja de ≈ US$16,790 a ≈ US$4,140, y mover a Glacier ya no conviene. Borrar a tiempo ahorra más que cualquier clase.
Con objetos grandes, el costo son los GB. Con millones de objetos chicos, mandan las requests. El log de C01 lo muestra.
Los mismos registros, guardados uno por objeto o juntos en archivos. Arranca con el log de C01: 10 millones de predicciones al día, de ≈ 300 bytes, un objeto por predicción, 90 días de retención y un job que lee el último mes una vez al mes. Precios de lista de S3 Standard en us-east-1 (noviembre de 2026): US$0.023 por GB-mes, US$0.005 por 1,000 PUT y US$0.0004 por 1,000 GET.
Un PUT cuesta lo mismo que guardar ≈ 217 KB un mes. Con objetos mucho más chicos que eso, mandan las requests; con objetos mucho más grandes, los GB.
Arranca con un objeto por predicción. Escribe 6944 registros por objeto (un archivo por minuto: 10 M ÷ 1,440 minutos del día) y mira cómo las requests pasan de casi todo a casi nada. Cada archivo de un minuto pesa ≈ 2 MB: ya basta para que las requests casi no cuesten. Para leer rápido conviene juntar todavía más, en archivos de ≈ 100 MB a 1 GB, y eso hace la compactación de la sección siguiente.
Data lake y particiones por fecha
EsencialData lake and date partitions
Ya tienes dónde guardar. Ahora falta organizar, para que alguien encuentre lo que busca entre millones de archivos.
Un lago de archivos
Un data lake es un object storage donde llega todo el dato de la empresa como archivos: logs, eventos de la app, etiquetas, copias de tablas. Se guarda tal como llegó y también ya procesado, y lo lee cualquier herramienta: Spark (un programa que reparte el trabajo de leer y transformar datos entre muchas máquinas), DuckDB (una base de datos chiquita para analizar, que corre en tu laptop), Athena (consultas SQL directo sobre los archivos de S3) o un script de Python.
La Ronda lo llama la fuente de verdad del camino offline, el que prepara el siguiente modelo sin que nadie espere: todo dataset de entrenamiento y todo recálculo del pasado salen de ahí. Casi siempre se organiza en zonas, cada una con su prefijo:
- Crudo (raw): tal como llegó, por ejemplo JSON lines del log. No se toca: si un paso posterior tenía un bug, se puede rehacer desde aquí.
- Procesado (processed): limpio, con tipos correctos, en Parquet. Es columnar y viene comprimido: los 3 GB diarios de log de C01 quedan en ≈ 0.3 a 0.6 GB.
- Curado (curated): tablas listas para usar, como un dataset de entrenamiento o los agregados diarios.
Así se vería el lake de C01, con un bucket y un prefijo por zona (un ejemplo; cada equipo elige sus nombres):
s3://c01-lake/
crudo/predicciones/dt=2026-11-06/... JSON lines, como llegaron
procesado/predicciones/dt=2026-11-06/... Parquet, una fila por predicción
curado/agregados_diarios/dt=2026-11-06/... conteos por categoría
curado/datasets/ds-2026-09-01/... el snapshot de un entrenamientoUn lago no obliga a nada. Cualquiera puede escribir cualquier archivo, y nadie revisa que cumpla el esquema: las columnas y sus tipos. El esquema lo descubre quien lee, al leer (schema on read). Si el equipo de la app renombró una columna el martes, el job de la noche se entera al fallar, o peor, sin fallar. Por eso los lagos sin reglas se vuelven pantanos, con archivos que nadie sabe qué son. Las capas de la sección siguiente ponen el orden: el warehouse y el lakehouse revisan el esquema al escribir.
Particionar por fecha
Si todo el log de un año estuviera en un solo prefijo, preguntar «¿cuántas fotos de tenis hubo ayer?» obligaría a leer el año entero. La solución es una partición (partition): dividir la tabla en grupos de archivos según el valor de una columna, casi siempre la fecha, y poner ese valor en la llave:
logs/predicciones/dt=2026-11-06/part-0000.parquet
El pedazo dt=2026-11-06 es una convención (columna=valor) que entienden Spark, Athena, DuckDB y los warehouses. dt es solo el nombre de la columna, por date; en la lección de formatos la viste como fecha=2026-11-05/, y funciona igual. Cuando la consulta dice «solo el 6 de noviembre», el motor lista ese prefijo y no abre nada más. Se llama partition pruning: podar las particiones que no sirven.
El lake de juguete de abajo tiene un mes de log: 4 archivos Parquet por día, de ≈ 125 MB cada uno. Leer «un día» es listar su prefijo.
import random
random.seed(7)
lake = {} # llave → bytes del archivo: solo importan las llaves
for dia in range(1, 31): # noviembre de 2026, 4 archivos Parquet por día
for parte in range(4):
llave = f"logs/predicciones/dt=2026-11-{dia:02d}/part-{parte:04d}.parquet"
lake[llave] = random.randint(100, 150) * 1_000_000
def leer(prefijos): # lo que hace un motor de consultas: listar y leer
llaves = [k for k in lake if any(k.startswith(p) for p in prefijos)]
return len(llaves), sum(lake[k] for k in llaves)
semana = [f"logs/predicciones/dt=2026-11-{d:02d}/" for d in range(1, 8)]
for nombre, prefijos in (("un día", ["logs/predicciones/dt=2026-11-06/"]),
("una semana", semana), ("el mes entero", ["logs/predicciones/"])):
n, b = leer(prefijos)
print(f"{nombre:>13}: {n:>3} archivos · {b / 1e9:5.2f} GB")
particiones = sorted({k.split("/")[2] for k in lake}) # como un LIST con delimitador «/»
print(len(particiones), "particiones:", particiones[0], "…", particiones[-1]) un día: 4 archivos · 0.50 GB
una semana: 28 archivos · 3.34 GB
el mes entero: 120 archivos · 14.92 GB
30 particiones: dt=2026-11-01 … dt=2026-11-30Leer un día abre 4 de los 120 archivos: un trigésimo del mes. La última línea hace lo que un LIST con delimitador «/»: en vez de todas las llaves, S3 devuelve solo los prefijos distintos hasta la siguiente «/», que aquí son las 30 particiones.
Particionar también hace que cada corrida procese una partición. El job de cada noche escribe solo dt=2026-11-06/. Si tenía un bug, se reescribe esa partición y nada más. Lo contrario, una tabla única que se reescribe entera cada noche, obliga a reprocesar todo para arreglar un día.
Se puede particionar por más de una columna, una dentro de otra. El log de predicciones de la Ronda (M12) va por día y por versión del modelo, dt=2026-11-06/model_version=v13/, para que el job que compara la versión nueva con la vieja lea solo las dos que le tocan. La columna que va primero es la que más se filtra.
Tres reglas para que funcione:
- Partir por lo que se filtra. La fecha casi siempre, porque casi toda pregunta empieza por «en estos días». Partir por categoría, si nadie filtra por categoría, solo multiplica archivos.
- Ni muy fino ni muy grueso. Particionar por hora y además por usuario daría millones de archivos diminutos, y ya viste que los objetos chicos se pagan en requests y en tiempo de listar. Se buscan archivos de ≈ 100 MB a 1 GB. Cuando un stream (un flujo de eventos que no para, tema de la lección siguiente) deja muchos archivos chicos, un job de compactación los junta cada noche en pocos grandes.
- ¿Qué fecha? Una predicción de las 23:59 puede llegar al lake a las 00:03. Si la partición usa la hora de llegada, cae en el día siguiente. Para entrenar importa la hora en que pasó, el event time, que verás en la lección de tiempo y hashes.
Warehouse, lakehouse y snapshots
EsencialWarehouses, lakehouses and snapshots
Dos maneras de usar datos: OLTP y OLAP
La base de datos del marketplace atiende millones de operaciones chiquitas: guardar una publicación, leer el usuario 42, cambiar un precio. Cada una toca pocas filas, completas, y tiene que tardar milisegundos. Eso se llama OLTP (online transaction processing, procesar transacciones en línea, mientras el usuario espera), y es lo que viste en la lección de bases de datos: tablas en una base relacional, con transacciones e índices.
Un analista pregunta otra cosa: «¿cuántas predicciones hubo por categoría en octubre, y cuántas aceptó la gente?». Su consulta toca millones de filas, pero solo dos o tres columnas, y puede tardar segundos. Eso es OLAP (online analytical processing, procesar para analizar).
Son formas tan distintas que piden almacenes distintos. Para OLTP conviene guardar cada fila junta; para OLAP, cada columna junta, como Parquet. La lección de formatos lo explicó: leer dos columnas de treinta en un formato columnar es leer ≈ 2/30 de los bytes (≈ 7 %), y menos con compresión. La diferencia entre OLTP y OLAP es la razón de que existan los warehouses.
Data warehouse
Un data warehouse es una base de datos hecha para OLAP: guarda las tablas por columnas, comprimidas, en su propio almacenamiento, y responde SQL repartiendo cada consulta entre muchas máquinas. Los más usados son BigQuery (Google), Snowflake y Redshift (AWS). Separan el almacenamiento del cálculo: guardas petabytes baratos y rentas máquinas solo mientras corre la consulta.
SELECT categoria, COUNT(*) AS fotos, AVG(CAST(aceptada AS INT64)) AS tasa_aceptacion
FROM c01.predicciones
WHERE dt BETWEEN '2026-10-01' AND '2026-10-31'
GROUP BY categoria
ORDER BY fotos DESC;Se lee casi en español: de la tabla c01.predicciones, toma las filas de octubre (WHERE), júntalas por categoría (GROUP BY) y, para cada grupo, cuenta las fotos y saca el promedio de aceptada, que vale 1 si la persona aceptó la categoría sugerida y 0 si no: ese promedio es la tasa de aceptación. Toca millones de filas, pero solo tres columnas: categoria, aceptada y dt.
BigQuery, en su modo por consulta, cobra por los bytes que lee: US$6.25 por TiB en su precio de lista de 2026, con el primer TiB de cada mes gratis. Ahí las particiones y las columnas se vuelven dinero. Si la consulta leyera el log crudo, como archivos JSON sin particiones, pagaría el año entero: ≈ 1.1 TB, ≈ US$6 por consulta. En Parquet, las tres columnas que usa esa consulta en las particiones de un mes son unos pocos GB: centavos.
¿Lake o warehouse? El lake es barato, guarda cualquier cosa y lo lee cualquier herramienta, pero no tiene transacciones: si un job muere a la mitad de escribir una partición, quien lea en ese momento ve archivos a medias. El warehouse da tablas con transacciones y SQL rápido, pero cuesta más y hay que cargarle los datos. Muchas empresas usan los dos: el lake guarda todo y el warehouse, las tablas que se consultan a diario.
Lakehouse: tablas encima de los archivos
Un lakehouse junta lo mejor de los dos: deja los datos como archivos Parquet en el lake y les pone encima un formato de tabla que da transacciones. Los tres más usados son Delta Lake (de Databricks), Apache Iceberg (nació en Netflix) y Apache Hudi (nació en Uber).
El truco es un registro aparte, guardado en el mismo bucket, que dice qué archivos forman la tabla en cada versión. Escribir es: subir los Parquet nuevos y, al final, agregar al registro una entrada que diga «la versión 3 son estos archivos». Hasta que esa entrada existe, nadie ve los archivos nuevos. Así cada escritura pasa completa o no pasa, y quien lee nunca ve una tabla a medias.
Con eso se puede:
- Corregir filas sueltas con un upsert (actualizar la fila si existe, insertarla si no) o borrarlas, algo que con Parquet solo no se puede, porque un objeto no se edita a la mitad. Hace falta, por ejemplo, para borrar los datos de una persona que lo pidió.
- Agregar columnas sin romper a quien lee (la evolución del esquema de la lección de formatos).
- Leer la tabla como estaba en una versión o una fecha: el time travel (viaje en el tiempo).
Snapshot: una foto fija para repetir un entrenamiento
Un snapshot es una foto fija de los datos en un momento: lo que había, y que ya no cambia aunque la tabla siga creciendo. En Iceberg, cada escritura crea uno. Para ML es la pieza que hace repetible un entrenamiento: el modelo de octubre guarda con qué snapshot se entrenó, y dentro de seis meses alguien puede volver a leer exactamente esas filas.
C01 lo hace sin copiar fotos. Su snapshot es un manifest: un archivo Parquet que lista la llave de cada foto, su etiqueta y una huella de su contenido (un hash SHA-256, que cambia si cambia un solo byte). Vive en un prefijo que no se reescribe, como datasets/ds-2026-09-01/, y el modelo guarda la huella del propio manifest. Un manifest pesa megabytes, así que puedes tener uno por mes durante años.
Para ir más hondoEl time travel no es para siempre+
En Delta Lake, por omisión, el historial dura 30 días y la limpieza (VACUUM) puede borrar los archivos viejos pasados 7; en Iceberg, la limpieza de snapshots (expire_snapshots) borra por omisión los de más de 5 días. Ninguna de las dos borra sola: corren cuando alguien las programa, y se programan para no pagar archivos viejos para siempre. Un snapshot que tiene que durar (el de un modelo en producción) se marca aparte, con su propia retención.
Llevar la cuenta de qué snapshot, qué código y qué contenedor produjeron cada modelo es el versionado de datos y el linaje: los verás a fondo en la estación 2 del Dojo, con DVC y lakeFS.
Feature store y backfill
ExtraFeature stores and backfills
El mismo número en dos lugares
Un modelo de fraude, como el de C09, usa features como «cuántas compras hizo esta tarjeta en las últimas 24 horas». Ese número se necesita en dos momentos muy distintos:
- Para entrenar: para cada transacción del pasado, el valor que tenía en ese momento. Son millones de filas, y se leen de una vez, en horas.
- Para servir: para la transacción de ahora, el valor de ahora, en un par de milisegundos.
Si cada equipo lo calcula a su manera, con un SQL para entrenar y un código distinto en el servicio, tarde o temprano los dos números se separan. Es el training-serving skew que viste en la lección de imágenes: el modelo aprendió con un número y en producción recibe otro.
Un feature store resuelve eso con una sola definición de cada feature y dos almacenes:
- El offline store: todas las versiones de cada valor, con su hora, en el lake o en el warehouse. Sirve para armar datasets de entrenamiento.
- El online store: solo el último valor de cada usuario o tarjeta, en una base base llave-valor como Redis o DynamoDB (la de AWS), que responde en milisegundos.
Un job copia, cada tanto, los valores nuevos del offline al online. A eso se le llama materializar. Herramientas conocidas: Feast (de código abierto), Tecton (desde 2025, parte de Databricks) y los feature stores de Databricks, SageMaker y Vertex AI.
- Data lake · eventos por dt=
Las transacciones y los eventos de cada día, en Parquet, en una partición por fecha. Es la fuente de verdad: todo lo de abajo se puede rehacer desde aquí. - Job de features · una sola definición
El código que calcula «compras de la tarjeta en las últimas 24 h». Es el mismo para la historia y para el presente: si hubiera dos versiones, sus números se separarían (training-serving skew). - Offline store · cada valor con su hora
Todas las versiones de cada valor, con su timestamp, en el lake o en el warehouse. De aquí salen los datasets de entrenamiento. - Dataset · point-in-time
Para cada ejemplo toma el valor que la feature tenía justo antes de ese momento (point-in-time correctness). Si tomara uno posterior, el modelo aprendería con el futuro: leakage. - Request · la tarjeta 77
Una transacción de ahora. El modelo tiene que decidir en milisegundos si la deja pasar. - Servicio del modelo · pide las features
Lee las features de la tarjeta del online store, con su llave (el id de la tarjeta), y se las da al modelo. No calcula nada histórico en el momento. - Online store · llave-valor · el último valor
Solo el valor más nuevo de cada tarjeta, en una base base llave-valor como Redis: responde en ≈ 1 ms. Cada llave lleva un TTL para que lo que ya nadie usa se borre solo.
Al armar un dataset, para cada ejemplo hay que tomar el valor que la feature tenía justo antes de ese momento, no el de después. Si no, el modelo aprende con información del futuro, un leakage. Esa unión se llama point-in-time join, y la verás con calma en la lección de tiempo y hashes: point-in-time correctness.
El online store solo guarda el presente, así que cada llave lleva un tiempo de vida (TTL): si una tarjeta no se usa en meses, su fila se borra sola y la memoria no crece sin fin.
¿C01 necesita un feature store? La Ronda dice que no: en visión pura, una foto entra y una categoría sale, y la feature es la imagen misma. Sí lo necesitan C08 (recomendación) y C09 (fraude), donde el modelo vive de la historia de cada usuario.
Backfill: recalcular el pasado
Inventas una feature nueva: «fotos que subió este vendedor en los últimos 7 días». Hoy empiezas a calcularla, pero para entrenar necesitas su historia, y el log de los últimos 90 días está en el lake. Correr el mismo cálculo sobre los días que ya pasaron es un backfill (rellenar hacia atrás).
Gracias a las particiones, un backfill es la misma corrida diaria, repetida una vez por cada día viejo.
Dos cuidados. El backfill corre el mismo código que la corrida diaria, no un script aparte escrito con prisa: si no, la historia y el presente vuelven a ser números distintos. Y escribe en el offline store, no en el online: a las requests de hoy no les sirve el valor de hace 90 días.
El backfill de C01 es otro: clasificar con el modelo las ≈ 200 millones de fotos que ya había en el catálogo. La Ronda lo parte en ≈ 2,000 pedazos de 100,000 fotos, cada uno con su archivo de salida. Al reanudar, se saltan los pedazos que ya tienen salida. Leer las 200 millones de fotos son 200 millones de GET: 200 M × US$0.0004 ÷ 1,000 = US$80.
Errores comunes
EsencialCommon mistakes
1. Usar el object storage como si fuera un disco
Abrir un objeto para agregarle una línea, editarlo a la mitad o «renombrar una carpeta» con un millón de fotos como si fuera instantáneo. O dos jobs que escriben la misma llave: gana el último, y el otro se pierde sin aviso.
Cómo evitarlo: diseñar con objetos que se escriben una vez. Llaves que no se repiten (con la fecha, la versión o el id del job), archivos nuevos en vez de editar los viejos y, si hace falta editar filas, un formato de tabla como Delta o Iceberg.
2. Millones de objetos chiquitos
Un objeto por predicción, por evento o por fila. Guardarlos es barato; subirlos, listarlos, moverlos de clase y leerlos, no. El log de C01 así cuesta ≈ US$1,650 al mes en vez de ≈ US$6.
Cómo evitarlo: juntar en archivos de ≈ 100 MB a 1 GB (Parquet, o pedazos de muchas fotos para entrenar). Y antes de una regla de ciclo de vida, contar los objetos, no solo los GB.
3. Creer que once nueves son un respaldo
La durabilidad protege de discos rotos, no de un DELETE, de una regla de ciclo de vida mal escrita o de un script con el prefijo equivocado.
Cómo evitarlo: versionado del bucket en lo que no se puede perder, Object Lock en lo que nadie debe borrar (el golden set, los snapshots de modelos en producción) y permisos que no dejen borrar a quien solo necesita leer.
4. Hacer público un bucket para «compartir rápido»
Un bucket público, o URLs prefirmadas de 7 días pegadas en un chat, con fotos de personas adentro.
Cómo evitarlo: el bucket privado siempre. Para compartir, URLs prefirmadas de una sola llave, de minutos, firmadas por un servicio que revisa quién las pide.
5. Mover a una clase fría lo que se sigue leyendo
Mandar a Standard-IA el dataset que se lee en cada entrenamiento, o a Deep Archive algo que alguien va a necesitar mañana. Pagas el GB leído, el mínimo de días y, en Deep Archive, horas de espera.
Cómo evitarlo: mirar cuántas veces se lee de verdad cada prefijo antes de escribir la regla. Si no lo sabes, Intelligent-Tiering, una clase de S3 que mueve cada objeto sola según su uso, a cambio de una cuota pequeña por objeto.
6. Una retención que nadie cumple
El bucket borra a los 90 días, pero las fotos siguen en snapshots, en copias y en laptops.
Cómo evitarlo: escribir la retención de cada artefacto al crearlo, no después, y que los snapshots se puedan buscar por la huella de cada foto para borrarla de todos.
En la vida real
ExtraIn real life
C01: dónde va cada cosa
Ya puedes responder la pregunta de la lección. Las cuentas son de la Ronda, con precios de S3 Standard.
| Qué | Dónde | Cuánto | Retención | Al mes |
|---|---|---|---|---|
| Fotos de las publicaciones | Bucket del producto, no de C01 | 2 TB al día | La del producto | La paga el marketplace |
| Log de cada predicción | Lake, Parquet por dt= | 3 GB al día crudo | 90 días; agregados para siempre | ≈ US$6 |
| Fotos que van a etiquetar | Bucket restringido, sin EXIF | ≈ 5,000 al mes, ≈ 1 GB | 90 días | Centavos |
| Golden set | Bucket restringido | 50,000 fotos, ≈ 10 GB | Sin caducar, borrado por huella | ≈ US$0.23 |
| Snapshots de entrenamiento | Prefijos fijos, manifest en Parquet | Megabytes cada uno | Sin caducar, borrado por huella | Centavos |
| Pesos de cada versión | Bucket de artefactos, junto al registro de modelos | ≈ 98 MB el ONNX | Las versiones que puedan volver | Centavos |
Todo lo propio de C01 cabe en menos de US$10 al mes. La Ronda lo resume en una frase: el almacenamiento es barato; lo caro es la privacidad de lo que guardas.
Lo que sí se nota son las requests y la red. En el diseño base, el gateway recibe los bytes de cada foto. M13 propone que la request a C01 lleve la llave de la foto y no sus bytes, si el GET extra cabe en el p99. Con esa variante, el gateway lee cada foto de S3 con un GET: 304 millones al mes, ≈ US$122. Y M13 advierte que si esos GET salieran por el NAT (la puerta que deja a las máquinas privadas llegar a internet, y que cobra por GB), los ≈ 61 TB al mes costarían ≈ US$2.7 mil más; por un camino privado hacia S3, nada. Lo verás en la lección de redes en la nube.
Los pesos, además, van horneados (copiados adentro) en la imagen del contenedor del servicio, y la estación 7 del Dojo lo explica: el nombre de versión de la imagen (su tag) es la versión del modelo.
C02: cámaras que suben clips
Las cajas de C02, en cada centro de distribución, suben fotos y clips de cada evento con una URL prefirmada de 15 minutos, directo a S3: los megabytes de video no cruzan la API. Los clips se guardan 30 días, porque traen personas. Si cada sitio mandara el video continuo de sus 40 cámaras serían ≈ 1.7 TB al día; solo con los clips de eventos, de ≈ 5 MB, son ≈ 10 GB.
C07 y C08: copias para reconstruir y lagos para aprender
C07, la búsqueda por foto, guarda en S3 una copia de cada vector que calcula, en Parquet por versión del modelo: ≈ 205 GB por versión, ≈ US$5 al mes. Con ella reconstruye el índice sin volver a usar la GPU. Los vectores que lee en cada búsqueda, en cambio, viven en un disco gp3 de cada máquina.
C08, la recomendación, guarda en su lake 90 días del log de lo que mostró, de los eventos de la app y de la historia de sus features (su offline store), particionado por día y hora. Solo el log, en Parquet, son ≈ 18 a 36 TB: ≈ US$0.4 a 0.8 mil al mes en Standard. Con los eventos y la historia de features, la Ronda calcula ≈ US$0.5 a 1 mil al mes.
C09: el lake que espera 90 días
En el fraude, la etiqueta llega tarde. Cada transacción y la decisión del modelo entran al lake el mismo día, pero solo se sabe si era fraude cuando el dueño de la tarjeta reclama un cargo (un contracargo), y eso puede tardar semanas. La Ronda usa una regla: si en 90 días no apareció un contracargo, la fila ya es un ejemplo negativo «maduro». Aquí la retención del lake no la pone solo el costo: sin 90 días de historia no hay etiquetas.
El cálculo en vivo de C09 guarda su estado, ≈ 24 GB de contadores (80 millones de tarjetas × ≈ 300 bytes), en el disco local de sus máquinas, y cada tanto deja en S3 un checkpoint: una copia de ese estado de la que puede volver a arrancar (el programa puede subir solo lo que cambió desde el checkpoint anterior). Es el mismo reparto de la sección extra de bloques: el disco para trabajar rápido, el object storage para no perder nada si la máquina muere.
C06: el mismo log en dos servicios
M13 compara dónde mandar ≈ 5.5 TB al mes de logs de C06, el caso de moderación de contenido. En CloudWatch Logs, el servicio de logs de AWS, cuesta US$0.50 por GB al recibirlos: 5,472 GB × 0.50 ≈ US$2,700 al mes. En S3, 5,472 GB × 0.023 ≈ US$126. Los mismos bytes, veinte veces de diferencia. Por eso C01 manda a CloudWatch solo los logs del servicio (errores, arranques), y los de cada predicción, a S3.
Fuera de ML: el archivo que nadie lee
Un banco tiene que guardar sus registros durante años, por ley, y casi nunca los vuelve a abrir. Es el uso típico de Deep Archive con Object Lock: guardar cuesta ≈ US$1 por TB al mes, nadie puede borrar nada antes de la fecha, y si un día un auditor pide un archivo, se espera unas horas. Lo mismo hacen los estudios de cine con sus copias maestras y los hospitales con sus imágenes viejas.
Ejercicios
EsencialExercises
Resuélvelos con lápiz antes de abrir la solución. Los de costo se pueden comprobar con las calculadoras. Usa los precios de S3 Standard de la lección.
- 1Fácil
En
s3://ml-datos/logs/dt=2026-11-06/part-0003.parquet, ¿cuál es el bucket y cuál la llave? ¿Qué devuelve un LIST con el prefijologs/dt=2026-11-0? Alguien quiere «renombrar la carpeta»logs/apredicciones/y tiene 50,000 objetos: ¿cuántas requests hace y cuánto cuestan?Ver la solución paso a paso
- Bucket:
ml-datos. Llave:logs/dt=2026-11-06/part-0003.parquet, todo lo que sigue. - El LIST devuelve las llaves de los días 1 al 9 de noviembre de 2026: un prefijo no tiene que terminar en «/».
- Renombrar no existe: 50,000
COPYy 50,000DELETE, más 50 LIST de 1,000 llaves. Son ≈ 100,050 requests. - Las COPY y los LIST se cobran como PUT: 50,050 × 0.005 ÷ 1,000 ≈ US$0.25. Los DELETE son gratis. Barato, pero no instantáneo, y quien lea a la mitad ve una parte en cada lado.
- Bucket:
- 2Fácil
Un equipo guarda mil millones de objetos en S3, con once nueves de durabilidad. ¿Cuántos esperaría perder al año? Y si el servicio tiene 99.99 % de disponibilidad, ¿cuántos minutos al año puede no contestar? ¿Se pierde algo en esos minutos?
Ver la solución paso a paso
- Durabilidad: 10⁹ × 10⁻¹¹ = 0.01 objetos al año: uno cada 100 años.
- Disponibilidad: 0.01 % de 525,600 minutos ≈ 53 minutos al año.
- En esos minutos no se pierde nada: las requests fallan, se reintenta y los objetos siguen ahí. Son dos medidas distintas.
- 3Fácil
Un millón de registros de 1 KB: ¿cuánto cuesta guardarlos un mes y cuánto subirlos, si cada uno es un objeto? ¿Y si los juntas en un solo archivo de 1 GB?
Ver la solución paso a paso
- Guardar: 1 GB × 0.023 = US$0.023 en los dos casos.
- Subir un millón de objetos: 10⁶ × 0.005 ÷ 1,000 = US$5, 217 veces lo que cuesta guardarlos un mes.
- Un solo archivo: un PUT (en la práctica, unas pocas partes), ≈ US$0.000005.
- 4Fácil
La API de C02 firma una URL de
PUTpara la llavesitio-07/clips/e-31.mp4, válida 15 minutos. ¿Qué puede hacer quien la tenga? ¿Puede leer otros clips, o subir uno a otra llave? ¿Y a los 20 minutos?Ver la solución paso a paso
- Puede subir un archivo a esa llave, una o varias veces, durante 15 minutos (900 segundos). Si sube dos veces, el segundo reemplaza al primero.
- No puede leer nada (la firma es para
PUT), ni escribir en otra llave: cambiar la llave rompe la firma y S3 responde 403. - A los 20 minutos ya venció: 403. La caja (la computadora del sitio) pide una URL nueva.
- Ojo: cualquiera que la copie puede hacer lo mismo durante esos 15 minutos. Por eso no se escribe en los logs.
- 5Medio
Guardas 1 TB de datos temporales que vas a borrar a los 10 días. ¿Sale más barato en Standard o en Standard-IA? ¿Y si los guardaras 60 días?
Ver la solución paso a paso
- Standard, 10 días: 1,000 GB × 0.023 × 10 ÷ 30.4 ≈ US$7.57.
- Standard-IA cobra mínimo 30 días: 1,000 × 0.0125 = US$12.50. Sale más caro, aunque su precio por GB es casi la mitad.
- A 60 días: Standard, 1,000 × 0.023 × 2 ≈ US$46; IA, 1,000 × 0.0125 × 2 = US$25, si no se lee. Leerlo todo una vez sumaría 1,000 × 0.01 = US$10, y todavía gana IA.
- 6Medio
El log de C01 en Parquet pesa ≈ 0.5 GB al día. Un analista corre cada mañana una consulta sobre los últimos 7 días. ¿Cuántos GB lee con particiones por día? ¿Y si la tabla no tuviera particiones y guardara un año? ¿Cuántas veces más?
Ver la solución paso a paso
- Con particiones: 7 × 0.5 = 3.5 GB.
- Sin particiones, el motor no sabe dónde está cada fecha y abre todo el año: 365 × 0.5 = 182.5 GB.
- 182.5 ÷ 3.5 ≈ 52 veces más, cada mañana. En BigQuery, que cobra por bytes leídos, es ≈ 52 veces el precio.
- 7Medio
C07 guarda una copia de sus vectores en S3: ≈ 205 GB por versión del modelo. Quiere conservar las últimas 6 versiones. ¿Cuánto cuesta al mes en Standard y en Glacier Instant Retrieval? ¿Cuánto cuesta leer una versión completa desde Glacier IR para reconstruir un índice?
Ver la solución paso a paso
- 6 × 205 = 1,230 GB.
- Standard: 1,230 × 0.023 ≈ US$28 al mes.
- Glacier IR: 1,230 × 0.004 ≈ US$4.92 al mes.
- Leer una versión desde Glacier IR: 205 × 0.03 ≈ US$6.15. Si las versiones viejas se leen menos de una vez al mes, conviene: deja la actual en Standard y las otras 5 en Glacier IR.
- 8Reto
Diseña el almacenamiento del log de C01 para un año, con la Ronda: filas crudas 90 días, agregados para siempre. Compara: (a) un objeto por predicción, en Standard; (b) un archivo por minuto. Para cada uno: GB guardados, costo de guardar, de los PUT y de leerlo una vez al mes. ¿Qué regla de ciclo de vida escribes?
Ver la solución paso a paso
- Guardado en los dos: 3 GB × 90 = 270 GB, ≈ US$6.2 al mes.
- (a) PUT: 10 M × 30.4 × 0.005 ÷ 1,000 ≈ US$1,520 al mes. Leer un mes: 304 M × 0.0004 ÷ 1,000 ≈ US$122. Total ≈ US$1,650.
- (b) PUT: 1,440 × 30.4 = 43,776 al mes, ≈ US$0.22. Leer un mes, 43,776 GET: ≈ US$0.02. Total ≈ US$6.4.
- La regla: borrar a los 90 días el prefijo de las filas crudas (
Expiration, 90 días) y ninguna regla sobre el de los agregados. No vale la pena mover el log a una clase fría: pesa poco y se lee para cada reentrenamiento. - En Parquet serían ≈ 0.3–0.6 GB al día: el guardado bajaría a ≈ 27–54 GB, ≈ US$1 al mes.
- 9Reto
El backfill del catálogo de C01: 200 millones de fotos, partidas en 2,000 pedazos iguales. Cada GPU T4 clasifica ≈ 1,000 fotos por segundo, y hay 4. (a) ¿Cuántas fotos lleva cada pedazo? (b) ¿Cuánto tarda todo? (c) ¿Cuánto cuestan los GET? (d) El pedazo 1,234 se cae a la mitad: ¿qué se repite, y qué tiene que cumplir cada pedazo para que repetirlo no haga daño?
Ver la solución paso a paso
- (a) 200,000,000 ÷ 2,000 = 100,000 fotos por pedazo.
- (b) 200 M ÷ (4 × 1,000 por segundo) = 50,000 s ≈ 14 horas.
- (c) 200 M × 0.0004 ÷ 1,000 = US$80.
- (d) Solo el pedazo 1,234: el job ve que no tiene archivo de salida y lo vuelve a correr. Para que eso sea seguro, cada pedazo escribe su salida en una llave fija, como
.../shard-01234.parquet, y solo al terminar: si se repite, reescribe el mismo objeto con lo mismo. Es idempotente.
Lo que sigue
EsencialWhat comes next
En la Ronda:
- M09 · Datos es esta lección hecha diseño: el data lake en Parquet particionado por
dt=, cada corrida sobre una partición, los backfills de 180 días, los snapshots con manifest y prefijos que no se pisan, Delta e Iceberg con su time travel, y el feature store con sus dos almacenes. - M13 · Nube recorre los bytes para encontrar los costos ocultos: S3 por GB y por request, objetos chicos contra Parquet, las equivalencias entre AWS, Google y Azure (S3, Cloud Storage, Blob; EBS, Persistent Disk; Redshift, BigQuery) y por qué los pesos se leen de S3 por un camino privado y no por internet.
- M12 · Monitoreo guarda el log de predicciones con retención escalonada (filas 90 días, agregados para siempre) y advierte la trampa de loguear la imagen «por si acaso».
- M02 · Patrones usa la URL prefirmada en los trabajos asíncronos y los pedazos con salida fija en el batch.
En el Dojo: la estación 1, «Datos y etiquetas», ya copia de S3 las fotos que hay que etiquetar, sin EXIF, a un bucket restringido. La estación 2, «Versionado y linaje», cuando abra, va a armar los snapshots con manifest y a versionarlos con DVC o lakeFS.
En Sensei: la siguiente lección, «Colas y streams», cuenta cómo llegan los eventos al lake, y «Tiempo, hashes e identificadores» explica las huellas de los manifests, el event time y el point-in-time join. Más adelante, las lecciones de regiones y redes en la nube explican por qué cuesta sacar datos de una región.
Palabras que vas a oír
EsencialWords you will hear
Estos son los conceptos que presentó esta lección. Cada uno tiene su tarjeta con la definición completa.
Object storageobject storage · almacenamiento de objetosUn almacén donde cada archivo es un objeto: sus bytes, una llave para encontrarlo y unos metadatos. Se le habla por HTTP (PUT para guardar, GET para leer) y guarda billones de objetos baratos y casi imposibles de perder. Los más conocidos son S3, de la nube de Amazon (AWS), y Cloud Storage, de la de Google.Más +
Un objeto no se edita a la mitad: un PUT a la misma llave lo reemplaza entero, y no se le pueden agregar líneas al final. Sí se puede leer un pedazo, con el header Range. Las llaves son texto plano y la «/» es una letra más: las carpetas que enseña la consola son prefijos que varias llaves comparten, y «renombrar una carpeta» es copiar y borrar cada objeto. Los objetos viven en un bucket, tienen durabilidad de once nueves y se cobran por GB-mes y por request, así que millones de objetos chiquitos salen caros. Es donde viven el data lake, los datasets, los pesos de los modelos y los logs. Se distingue del almacenamiento de bloques (un disco de una máquina) y del de archivos (una carpeta compartida).
Analogía. Un guardarropa con boletos: entregas la chamarra, te dan un número y con ese número la recuperas, entera. No puedes pedir que le cosan un botón ahí adentro: te la llevas, la arreglas y la vuelves a dejar. Se rompe en dos cosas: aquí tú eliges el número (la llave), y puedes pedir la lista de todos los números que empiezan igual (un LIST con prefijo), algo que ningún guardarropa hace.
Ejemplo. La foto de Ana se guarda con PUT en la llave fotos/2026/11/06/ana-tenis.jpg del bucket del marketplace. C01 la lee con un GET a esa llave. Cambiar un solo byte obliga a subir los 200 KB otra vez.
Bucket (de objetos)bucket · object storage bucketEl contenedor donde se guardan los objetos de un object storage, con un nombre propio y sus reglas: quién entra, cuánto dura cada cosa y si guarda versiones viejas. No es el bucket de un histograma, que es un intervalo.Más +
En S3, el nombre de cada bucket es, por omisión, único en el mundo (desde marzo de 2026 también se puede crear con un sufijo de tu cuenta y la región, solo tuyo), y el bucket vive en una región. La dirección de un objeto junta el bucket y la llave: en s3://ml-datos/logs/dt=2026-11-06/part-0001.parquet, el bucket es ml-datos. Cada bucket lleva su bucket policy (los permisos), sus reglas de ciclo de vida, su versionado y, si se quiere, Object Lock (versiones que nadie puede borrar antes de una fecha). Lo normal es separar los datos por bucket según quién debe verlos: en C01, las fotos para etiquetar van a un bucket restringido, sin EXIF. Ojo con la palabra: en la lección de percentiles, un bucket es el intervalo de un histograma.
Ejemplo. C01 tiene un bucket de lake (c01-lake) para los logs y los snapshots, y otro restringido para el golden set y las fotos que van a etiquetar. Nadie con permiso solo de leer el lake puede ver esas fotos.
URL prefirmadapresigned URL · signed URL · URL firmadaUna dirección web que trae escrito adentro, en su query, un permiso firmado: hacer una sola operación (subir o bajar) sobre un solo archivo de un bucket, durante un rato corto que elige el servidor que la firma, por ejemplo 15 minutos. Quien la tenga la puede usar sin tener las claves del almacén.Más +
La firma la calcula un servidor que sí tiene permiso, con su clave secreta, sin llamar al object storage: es una cuenta local. Cubre el método (PUT o GET), el bucket, la llave, la hora y cuántos segundos vale, y a veces headers como el Content-Type. Al recibir la request, S3 recalcula la firma: si algo cambió, responde 403; si venció, también. Además revisa que quien firmó todavía tenga permiso. Como el permiso viaja en la URL, la request no lleva header Authorization. En S3 dura como mucho 7 días, y menos si se firmó con credenciales temporales. Sirve para que una app o una cámara suban archivos directo al bucket, sin que los bytes crucen la API, y para que un cliente baje un resultado privado. Es como un boleto: si se filtra, sirve hasta que vence; por eso se firma para una llave, con vencimiento corto, y no se escribe en los logs. Google la llama signed URL.
Analogía. Un pase de estacionamiento que te da la caseta: abre una sola pluma, una vez, durante 15 minutos, y no dice tu nombre. Se rompe en que el pase de verdad se pierde al usarlo; una URL prefirmada se puede usar varias veces mientras no venza.
Ejemplo. En C02, la API firma para la caja de cada sitio una URL de PUT a la llave sitio-07/clips/e-31.mp4, con X-Amz-Expires=900: 15 minutos. La caja sube el clip directo a S3; si tarda 20 minutos, recibe 403 y pide otra.
DurabilidaddurabilityLa probabilidad de que un dato que guardaste siga ahí, intacto, después de un año. S3 está diseñado para once nueves (99.999999999 %): con 10 millones de objetos, perderías uno cada 10,000 años.Más +
En S3 Standard se logra guardando cada objeto repartido en muchos discos de al menos tres zonas de disponibilidad (centros de datos separados), con huellas que detectan si un bit se dañó y reparando rápido cuando un disco muere. No es lo mismo que la disponibilidad: esa mide si el servicio contesta ahora (S3 Standard está diseñado para 99.99 %, ≈ 53 minutos al año de fallas, aunque su contrato promete 99.9 % al mes). Un bucket puede no contestar un rato sin perder nada, y al revés: con disponibilidad perfecta, un DELETE tuyo borra el objeto para siempre. La durabilidad protege del hardware, no de los errores humanos; para eso están el versionado del bucket, Object Lock y las copias en otra cuenta o región. Las copias tienen que fallar por separado: tres discos con la misma fuente de luz no valen como tres.
Ejemplo. Las fotos de un año del marketplace son 3,650 millones. Con 10⁻¹¹ de probabilidad de perder cada una al año, esperarías perder 0.0365 al año: una cada ≈ 27 años.
Clase de almacenamientostorage classCada una de las maneras de guardar un objeto en el mismo object storage, más caras o más baratas según qué tan seguido y qué tan rápido lo vas a leer. En S3 van de Standard (US$0.023 por GB al mes, precio de lista del norte de Virginia en 2026) a Glacier Deep Archive (≈ US$0.001), con la misma durabilidad.Más +
Lo que cambia es el trato: cuánto cuesta guardar, cuánto cuesta leer y cuánto hay que esperar. Standard se lee al instante, sin cargo por GB. Standard-IA (Infrequent Access) cuesta casi la mitad, pero cobra US$0.01 por GB leído, un mínimo de 30 días y un mínimo de 128 KB por objeto. Glacier Instant Retrieval cuesta ≈ US$0.004 y cobra US$0.03 por GB leído, con mínimos de 90 días y 128 KB por objeto. Glacier Flexible Retrieval y Deep Archive son para archivo: leerlos tarda de minutos a horas. Mover un objeto de clase es una request que se cobra por objeto, así que con millones de objetos chicos mover puede costar más de lo que ahorra. Intelligent-Tiering mueve cada objeto solo, según su uso, por una cuota pequeña. Las mueven las reglas de ciclo de vida. Google tiene la misma escalera: Standard, Nearline, Coldline y Archive.
Ejemplo. La copia de los vectores de C07 pesa ≈ 205 GB por versión: ≈ US$4.70 al mes en Standard y ≈ US$0.82 en Glacier Instant Retrieval. Leer una versión entera desde Glacier IR para reconstruir el índice cuesta ≈ US$6.15.
Regla de ciclo de vidalifecycle rule · lifecycle policyUna regla de un bucket que mueve o borra objetos según su edad, sin que ningún programa tuyo lo haga: «a los 30 días, pásalo a una clase más barata, como Glacier; a los 365, bórralo».Más +
Tiene dos acciones: mover (transition) a una clase más barata y borrar (expiration). Cada regla aplica a un prefijo o a los objetos con una etiqueta, así que cada parte del bucket puede tener la suya, y S3 las revisa más o menos una vez al día. Es la manera de cumplir una retención: los logs crudos de C01 se borran a los 90 días con una regla. Cuidados: cada transición se cobra por objeto (con millones de fotos chicas puede comerse el ahorro), las clases frías cobran un mínimo de días, y una regla mal escrita borra en silencio lo que no debía. Con el versionado prendido, borrar deja la versión vieja, y hace falta otra regla para las versiones no actuales.
Ejemplo. El bucket de fotos del marketplace: 30 días en Standard, después Glacier Instant Retrieval, borrado al año. Al mes cuesta ≈ US$10,140 en vez de ≈ US$16,790, y US$6,080 de eso son las 304 millones de transiciones.
Almacenamiento de bloquesblock storageUn disco en crudo, visto como una fila de bloques numerados, sobre el que la máquina pone su propio sistema de archivos. En la nube es un disco de red pegado a una sola máquina, como EBS en AWS.Más +
Se puede leer y escribir a la mitad de un archivo, con latencias de milisegundos o menos, así que ahí van el disco con el que arranca la máquina y las bases de datos. A cambio, normalmente lo usa una sola máquina a la vez, vive en una sola zona de disponibilidad y se paga por los GB reservados, se usen o no: un gp3 de EBS cuesta ≈ US$0.08 por GB-mes, unas 3.5 veces S3 Standard, y da de base 3,000 IOPS y 125 MiB/s. Las otras dos maneras de guardar en la nube son el almacenamiento de archivos (una carpeta compartida por NFS que montan muchas máquinas, como EFS, ≈ US$0.30 por GB-mes) y el de objetos. El disco NVMe local de una máquina (instance store) es más rápido, pero se pierde con ella: sirve de caché, nunca de único lugar.
Ejemplo. C07 guarda en un disco gp3 de cada máquina los 51.2 GB de vectores que lee en cada búsqueda, servidos desde el page cache. La copia que no se puede perder va a S3.
Data lakedata lakeUn object storage donde llegan todos los datos de una empresa como archivos, crudos y procesados, para que cualquier herramienta los lea. Es la fuente de verdad de lo que se prepara sin que nadie espere: de ahí salen los datasets de entrenamiento y los recálculos del pasado.Más +
Suele tener zonas, cada una con su prefijo: crudo (tal como llegó, por ejemplo JSON lines), procesado (limpio, en Parquet) y curado (tablas listas, como un dataset o los agregados diarios). Los datos se organizan en particiones por fecha para leer solo lo necesario. Lo leen Spark, DuckDB, Athena o un script de Python. Es barato y no obliga a nada: cualquiera escribe cualquier archivo, y el esquema lo descubre quien lee. Sin reglas se vuelve un pantano. Le faltan las transacciones de un warehouse; un lakehouse se las agrega encima.
Ejemplo. El log de predicciones de C01 llega al lake cada pocos minutos, en Parquet particionado por dt=: ≈ 0.3 a 0.6 GB al día. De ahí salen el monitoreo de drift y el dataset de cada reentrenamiento.
Data warehousedata warehouseUna base de datos hecha para analizar: guarda las tablas por columnas y responde consultas en SQL (el lenguaje para pedirle datos a una tabla) sobre millones de filas repartiendo la consulta entre muchas máquinas. Los más usados son BigQuery, Snowflake y Redshift.Más +
Es la respuesta al lado OLAP: consultas que tocan muchísimas filas pero pocas columnas. Guarda cada columna junta y comprimida, así que leer tres columnas de treinta cuesta una fracción. Separa el almacenamiento del cálculo: guardas mucho barato y rentas máquinas solo mientras corre la consulta. Algunos cobran por bytes leídos (BigQuery, en su modo por consulta, US$6.25 por TiB en 2026), y ahí las particiones y elegir columnas se vuelven dinero. Frente a un data lake da tablas con transacciones, esquema revisado al escribir y SQL rápido, a cambio de costar más y de que hay que cargarle los datos. Muchas empresas tienen los dos.
Ejemplo. Un analista de C01 pregunta cuántas predicciones hubo por categoría en octubre y cuántas aceptó la gente. Con particiones por día y tres columnas, la consulta lee unos pocos GB en vez del año entero.
OLTP y OLAPOLTP vs OLAP · online transaction / analytical processingLas dos maneras de usar datos. OLTP: millones de operaciones chiquitas, cada una sobre pocas filas completas, en milisegundos (guardar una publicación). OLAP: pocas consultas grandes, sobre millones de filas pero pocas columnas (cuántas ventas por categoría en un mes).Más +
Piden almacenes distintos. Para OLTP conviene guardar cada fila junta, con índices y transacciones: es una base relacional como Postgres. Para OLAP conviene guardar cada columna junta y comprimida, como Parquet o un data warehouse. Correr analítica pesada en la base de OLTP del producto la vuelve lenta para los usuarios; por eso los datos se copian a un lake o a un warehouse para analizarlos.
Ejemplo. OLTP: «lee la publicación 8f3a», una fila, en 2 ms. OLAP: «predicciones por categoría en octubre», 300 millones de filas y 3 columnas, en unos segundos.
Lakehouselakehouse · open table formatUn data lake con tablas de verdad: los datos siguen como archivos Parquet en el object storage, y un registro aparte dice qué archivos forman la tabla en cada versión. Así cada escritura pasa completa o no pasa, se pueden corregir filas y se puede leer una versión vieja. Los formatos más usados son Delta Lake, Apache Iceberg y Apache Hudi.Más +
Escribir es subir archivos nuevos y, al final, agregar al registro una entrada con la versión nueva: hasta entonces nadie los ve, así que cada escritura pasa completa o no pasa. Los archivos nunca se editan: borrar filas reescribe un archivo y la versión nueva deja de apuntar al viejo. Por eso se puede leer la tabla como estaba en una versión o una fecha (time travel) sin copiar datos. El time travel dura lo que dura la limpieza: en Delta, por omisión, el historial dura 30 días y los archivos viejos se pueden borrar pasados 7; en Iceberg, la limpieza borra snapshots de más de 5 días. Lo que tiene que durar se marca aparte. Delta nació en Databricks, Iceberg en Netflix y Hudi en Uber.
Ejemplo. El log de predicciones de C01 como tabla Iceberg: el job de la noche agrega los archivos del día en una sola transacción, y una solicitud de borrado quita las filas de una persona creando una versión nueva. El snapshot del dataset de septiembre se marca con una retención de 365 días.
Partición (de datos)partition · data partitioningCada grupo en que se divide una tabla grande según el valor de una columna, casi siempre la fecha, con ese valor escrito en la llave: dt=2026-11-06/. Así una consulta o un job lee solo los días que necesita y no el año.Más +
La convención columna=valor la entienden Spark, Athena, DuckDB y los warehouses: si la consulta filtra por fecha, el motor lista solo esos prefijos (partition pruning). También hace que cada corrida diaria escriba solo su partición, así que un error se arregla reescribiendo un día, y que un backfill sea la misma corrida repetida por cada día viejo. Se puede partir por más de una columna (dt=…/model_version=v13/). Reglas: partir por lo que más se filtra, no hacer particiones tan finas que dejen millones de archivos chiquitos (se buscan de ≈ 100 MB a 1 GB) y decidir si la fecha es la de llegada o la del evento (event time). No es la partición de un tópico de Kafka (partición del tópico), que reparte mensajes entre consumidores.
Ejemplo. Con el log de C01 en Parquet, ≈ 0.5 GB al día, una consulta de los últimos 7 días lee 3.5 GB con particiones y 182.5 GB sin ellas, si la tabla guarda un año: ≈ 52 veces más.
SnapshotsnapshotUna foto fija de los datos en un momento: lo que había entonces, que ya no cambia aunque la tabla siga creciendo. Hace repetible un entrenamiento: el modelo guarda con qué snapshot se entrenó.Más +
En un lakehouse, cada escritura crea un snapshot, y el time travel lee uno viejo; dura hasta que la limpieza lo borra, así que el de un modelo en producción se marca con su propia retención. Otra forma, la de C01: un manifest, un archivo que lista la llave de cada foto, su etiqueta y su hash, en un prefijo que nunca se reescribe; no copia fotos y pesa megabytes. Un snapshot también debe respetar la retención: si alguien pide borrar su foto, hay que poder encontrarla en todos. La palabra se usa igual para otras cosas: un snapshot de EBS es una copia de un disco. Llevar la cuenta de qué snapshot, qué código y qué contenedor produjeron cada modelo es el versionado de datos y el linaje.
Ejemplo. El modelo de C01 de septiembre apunta a datasets/ds-2026-09-01/, con la huella SHA-256 del manifest. Seis meses después, alguien vuelve a armar exactamente el mismo dataset y repite el entrenamiento.
Retencióndata retentionCuánto tiempo se conserva cada dato antes de borrarlo. La deciden el costo, la ley y la privacidad, y lo que el ML necesita para reentrenar y comparar modelos.Más +
Se decide al crear cada artefacto, no después, y se cumple con reglas de ciclo de vida (en S3), con un TTL o con un job de purga (en una tabla). La retención real es la del artefacto que más dura: si el bucket borra a los 90 días pero la foto sigue en un snapshot, en un respaldo en otra región o en un CSV en una laptop, sigue existiendo. Un dataset no puede ser la puerta trasera de la retención. Lo común es una retención escalonada: filas crudas por semanas o meses, agregados (que no traen datos de nadie) para siempre.
Ejemplo. C01: logs de predicción, 90 días; copias para etiquetar, 90 días; agregados diarios, para siempre; golden set y snapshots, sin caducar, pero borrados por hash cuando alguien lo pide. Si el golden set caducara, ya no podrías comparar modelos de meses distintos.
Feature storefeature storeUn sistema que guarda las features de un modelo (los números que recibe, como «compras de esta tarjeta en 24 h») con una sola definición para entrenar y para servir: un almacén offline con toda la historia y uno online con el valor de ahora, que responde en milisegundos.Más +
El offline store guarda todas las versiones de cada valor con su hora, en el lake o el warehouse: de ahí salen los datasets, tomando para cada ejemplo el valor de justo antes de su momento (point-in-time correctness), para no aprender del futuro (leakage). El online store guarda solo el último valor de cada usuario o tarjeta en una base base llave-valor como Redis. Un job copia los valores nuevos del uno al otro (materializar). Como los dos salen del mismo código, se evita el training-serving skew. Herramientas: Feast (de código abierto), Tecton (desde 2025, parte de Databricks) y los de Databricks, SageMaker y Vertex AI. En visión pura, como C01, casi nunca hace falta: la feature es la imagen.
Ejemplo. C09 usa «compras de la tarjeta en las últimas 24 h». Para entrenar, una transacción de las 10:05 toma el valor de las 10:00 del offline store; en producción, el servicio lee el valor actual del online store en ≈ 1 ms.
BackfillbackfillRecalcular el pasado: correr un cálculo nuevo sobre datos viejos, como una feature nueva sobre los últimos 90 días o un modelo sobre todo el catálogo que ya existía.Más +
Con los datos en particiones por fecha, un backfill es la corrida diaria repetida una vez por cada día viejo, varias a la vez. Para que se pueda reanudar, cada corrida escribe solo su partición (o su pedazo) en una llave fija, de modo que repetirla da lo mismo (idempotencia). Debe usar el mismo código que la corrida diaria, o la historia y el presente vuelven a ser números distintos, y escribir en el almacén offline, no en el online. Es un trabajo de throughput, no de latencia: va por el camino offline, en tandas y sin tocar el servicio.
Ejemplo. Una feature nueva con 90 particiones de ≈ 20 minutos son 30 h en serie y ≈ 3 h con 10 a la vez. El backfill de C01, clasificar 200 millones de fotos viejas en ≈ 2,000 pedazos, tarda ≈ 14 h con 4 GPUs y paga ≈ US$80 de GET a S3.
Chequeo
EsencialCheck
Intenta responder en tu cabeza antes de abrir cada respuesta.
1¿Por qué no se puede «editar a la mitad» un objeto de S3, y qué haces si necesitas cambiarlo?Ver respuesta
Porque solo guarda objetos enteros: un PUT a la misma llave reemplaza todo, y esa sencillez le deja repartir billones de objetos sin coordinar escrituras. Lo bajas, lo cambias y lo subes entero; para editar filas, Delta o Iceberg.
2¿Qué permite una URL prefirmada y quién la firma?Ver respuesta
Una operación (PUT o GET) sobre una llave, por un rato. La firma con su clave secreta un servidor con permiso, y quien tenga la URL la usa hasta que vence.
3Once nueves de durabilidad, ¿quieren decir que tus datos están a salvo?Ver respuesta
De los discos rotos, sí: perderías uno de 10 millones cada 10,000 años. De un DELETE, una regla mal escrita o un prefijo equivocado, no: para eso, versionado, Object Lock y permisos.
4¿Por qué un ciclo de vida que mueve millones de fotos chicas a una clase fría puede ahorrar poco?Ver respuesta
Porque cada transición se cobra por objeto: mover 304 millones de fotos al mes a Glacier IR cuesta ≈ US$6,080, casi la mitad del ahorro en GB; a Deep Archive, más que todo el ahorro.
5¿Para qué sirve particionar un log por
dt=?Ver respuestaPara leer solo los días necesarios: una semana son 3.5 GB en vez de los 182.5 del año. Y para que cada corrida reescriba solo su día si algo sale mal.
6¿Qué le agrega un lakehouse a un data lake?Ver respuesta
Un registro de qué archivos forman la tabla en cada versión. Con él, cada escritura pasa completa o no pasa, se corrigen filas y se lee una versión vieja (time travel), sin copiar datos.