db-reservas resuelve muy bien el problema de que una plaza no se venda dos veces, pero es una mala casa para el catálogo de tarifas de Contoso Airlines. Una tarifa "Flex Business Larga Distancia" tiene condiciones de cambio, equipaje permitido, acumulación de puntos, penalizaciones por tramo y restricciones por temporada; una tarifa "Básica Nacional" tiene cuatro campos. Normalizar eso significa veinte tablas y consultas con diez uniones para responder algo tan simple como "dame esta tarifa entera". Además, el catálogo se lee miles de veces por minuto desde la web y desde la API de Disponibilidad, se escribe dos veces al día, y hay clientes en Europa y en América esperando la respuesta.

Ese es exactamente el terreno de Azure Cosmos DB: una base de datos NoSQL distribuida globalmente, con latencia garantizada de un dígito en milisegundos, escalado elástico y esquema flexible. Esta lección la despliega para el catálogo de tarifas y los perfiles de pasajero, y se detiene con calma en las dos decisiones que la gente toma mal: la clave de partición y el nivel de consistencia.

Aviso de coste importante: Cosmos DB puede ser barato o carísimo según cómo se configure. Un contenedor con 400 RU/s aprovisionadas cuesta unos 23 € al mes y factura aunque nadie lo use; activar escrituras multirregión multiplica el coste por región. Para aprender, usa el nivel gratuito (1000 RU/s y 25 GB sin coste, una cuenta por suscripción) o el modo sin servidor, y elimina la cuenta al terminar.

Contenido

  1. Qué problema resuelve que no resuelve una base relacional
  2. Las API disponibles y cuál elegir
  3. Modelo de recursos: cuenta, base de datos, contenedor y elemento
  4. La clave de partición: la decisión más irreversible
  5. Unidades de solicitud (RU/s) y modelos de capacidad
  6. Los cinco niveles de consistencia
  7. Distribución global y escrituras multirregión
  8. Despliegue con Azure CLI
  9. Documentos de tarifas: inserción y consulta
  10. Política de indexación y tiempo de vida
  11. La fuente de cambios como base de la integración
  12. Copias de seguridad continuas y control del gasto
  13. Errores Comunes y Consejos
  14. Ejercicios
  15. Conclusión

  1. Qué problema resuelve que no resuelve una base relacional

Azure SQL Database escala verticalmente: si necesitas más, subes de nivel, hasta que llegas al techo de la máquina. Cosmos DB escala horizontalmente y de forma transparente: reparte los datos entre particiones físicas que el servicio añade solo, sin que tú hagas nada, y puede replicar esas particiones en tantas regiones como quieras con un clic. Las diferencias que importan al decidir:

Azure SQL Database Azure Cosmos DB
Esquema Fijo, validado por el motor Flexible: cada documento puede diferir
Escalado Vertical, con techo Horizontal y transparente, prácticamente sin techo
Latencia garantizada No hay SLA de latencia Un dígito en ms para lecturas y escrituras por clave
Distribución global Réplicas configuradas a mano Añadir una región es una operación de un paso
Consultas entre entidades Uniones arbitrarias, potentes Solo dentro del documento; uniones entre contenedores, no
Transacciones ACID en toda la base ACID dentro de una partición lógica
Facturación vCore u horas de DTU Unidades de solicitud consumidas

La conclusión no es que uno sea mejor: es que responden preguntas distintas. Si tu consulta cruza entidades que nadie previó, quieres SQL. Si tu consulta es "dame este documento por su clave, rápido, desde cualquier continente, y que no me importe cuántos millones haya", quieres Cosmos DB.

  1. Las API disponibles y cuál elegir

Cosmos DB es un motor con varias caras compatibles con protocolos existentes. La API se elige al crear la cuenta y no se puede cambiar después:

API Qué habla Elígela cuando…
NoSQL (antes SQL/Core) JSON con consultas de sintaxis tipo SQL Es un proyecto nuevo: recibe primero cada novedad y tiene la mejor documentación y SDK
MongoDB Protocolo de MongoDB Migras una aplicación que ya usa MongoDB y no quieres tocar el código
Cassandra CQL Migras una carga de Cassandra existente
Gremlin Consultas de grafo El modelo es una red: rutas, relaciones, recomendaciones
Table Protocolo de Azure Table Storage Necesitas Table Storage pero con latencia garantizada e índices

Contoso elige la API NoSQL por tres motivos concretos: es un desarrollo nuevo sin nada que migrar, las funcionalidades nuevas llegan siempre primero a esta API, y el equipo de Diego Salas ya escribe consultas SQL, así que la sintaxis les resulta familiar desde el primer día.

  1. Modelo de recursos: cuenta, base de datos, contenedor y elemento

La jerarquía tiene cuatro niveles y cada uno decide algo distinto:

  • Cuenta (cosmos-contoso-tarifas-pro): el límite de la API, de las regiones, de la consistencia predeterminada y de las claves de acceso. Es el recurso que aparece en el portal y en la factura.
  • Base de datos (catalogo): agrupación lógica; puede tener rendimiento compartido por todos sus contenedores.
  • Contenedor (tarifas, perfiles): la unidad real de escalado y distribución. Aquí se define la clave de partición, el rendimiento y la política de indexación. Es el equivalente conceptual a una tabla, pero sin esquema.
  • Elemento: el documento JSON. Cada uno tiene un id obligatorio y su valor de clave de partición; la pareja id + clave de partición identifica de forma única un elemento.

  1. La clave de partición: la decisión más irreversible

Cosmos DB agrupa los elementos que comparten valor de clave de partición en una partición lógica, y reparte esas particiones lógicas entre particiones físicas de hasta 50 GB y 10.000 RU/s. Toda la escalabilidad depende de que ese reparto sea uniforme. Una buena clave de partición cumple tres cosas a la vez:

  1. Cardinalidad alta: muchos valores distintos, para que haya muchas particiones lógicas.
  2. Reparto uniforme de peticiones y datos, sin valores mucho más activos que otros.
  3. Aparece en la mayoría de las consultas, para que estas se resuelvan en una sola partición.

Aplicado al catálogo de tarifas de Contoso:

Candidata Cardinalidad Reparto ¿Aparece en las consultas? Veredicto
/origenDestino ("BCN-CDG") Alta: ~600 rutas Uniforme; ninguna ruta concentra el grueso Sí: siempre se busca por ruta Correcta
/fecha Media Pésimo: todo el tráfico de hoy cae en la partición de hoy Sí Partición caliente
/tipoTarifa ("basica", "flex") Baja: 5 valores Muy desigual y con techo de 50 GB por partición Sí Inservible
/id Máxima Perfecto No: casi ninguna consulta filtra por id Toda consulta cruza particiones

El caso de /fecha merece detenerse, porque es el error más repetido del sector. Parece razonable: las tarifas se consultan por fecha de vuelo. Pero el 90 % de las consultas se refieren a los próximos 30 días, así que un puñado de particiones lógicas recibe casi todo el tráfico mientras el resto duerme. Ese desequilibrio se llama partición caliente: aunque el contenedor tenga 10.000 RU/s, cada partición física solo puede usar su parte, así que empiezan a llegar errores de límite excedido (código 429) con el contenedor globalmente ocioso.

Y por qué es irreversible: la clave de partición de un contenedor no se puede cambiar. Corregirla obliga a crear un contenedor nuevo y migrar todos los datos, con la aplicación escribiendo en los dos durante la transición. Por eso esta decisión se toma escribiendo antes las consultas, no después.

Si ninguna propiedad sirve por sí sola, se usa una clave sintética: concatenar dos campos ("BCN-CDG_2026-07") para subir la cardinalidad manteniendo el filtro habitual.

  1. Unidades de solicitud (RU/s) y modelos de capacidad

Una unidad de solicitud (RU) es la moneda de Cosmos DB: normaliza el coste de CPU, memoria y E/S de cada operación. La referencia es que leer por id un documento de 1 KB cuesta 1 RU. Una escritura de ese mismo documento cuesta unas 5 RU, y una consulta que recorre muchos documentos puede costar cientos. Lo que contratas es un caudal: RU por segundo.

Modelo Cómo factura Cuándo usarlo
Aprovisionado estándar Pagas las RU/s contratadas las 24 horas Carga sostenida y previsible
Autoescalado Fijas un máximo; escala entre el 10 % y el 100 % y factura el pico de cada hora Carga variable; cuesta un 50 % más por RU pero suele salir más barato
Sin servidor Pagas solo las RU consumidas Desarrollo, pruebas, cargas esporádicas
Nivel gratuito 1000 RU/s y 25 GB sin coste Aprender y prototipar (una cuenta por suscripción)

Lo mejor de este modelo es que cada respuesta te dice lo que ha costado, en la cabecera x-ms-request-charge. Es la forma de optimizar sin adivinar:

# El SDK y el portal muestran el cargo de cada operacion. Ejemplo de dos consultas:
#   SELECT * FROM c WHERE c.origenDestino = 'BCN-CDG'   ->  2,89 RU  (una particion)
#   SELECT * FROM c WHERE c.equipajeIncluido = true     -> 48,60 RU  (todas las particiones)

Esas dos cifras cuentan toda la historia: la primera consulta lleva la clave de partición y se resuelve en una sola; la segunda es una consulta entre particiones y cuesta 17 veces más. Para estimar el caudal necesario basta multiplicar: si Contoso espera 900 lecturas por segundo de 3 RU cada una, necesita unas 2700 RU/s más margen para los picos.

  1. Los cinco niveles de consistencia

Aquí es donde el teorema CAP de la lección 03-01 se vuelve una casilla de configuración. Cosmos DB ofrece cinco niveles, de más estricto a más relajado, y se pueden relajar por petición desde el SDK:

Nivel Qué garantiza Latencia de lectura Coste en RU de lectura Ejemplo en Contoso
Fuerte Todos leen siempre la última escritura confirmada La más alta; no permite escrituras multirregión Doble Inventario de plazas, si viviera aquí
Obsolescencia limitada Retraso acotado por número de versiones o por tiempo Media Doble Cupos de plazas por tarifa con margen de 5 segundos
Sesión (predeterminado) Un mismo cliente ve siempre sus propias escrituras Baja Normal Perfiles de pasajero: cambias tu asiento y lo ves
Prefijo coherente Nunca ves las escrituras desordenadas, pero sí con retraso Baja Normal Historial de cambios de una tarifa
Eventual Al final converge; sin orden garantizado La más baja Normal Catálogo de tarifas: cambia dos veces al día

Aplicado al ejemplo del inventario de plazas: con consistencia eventual, dos clientes en Madrid y en Bogotá podrían leer a la vez que quedan 2 plazas cuando en realidad ya solo hay 1, y venderías un asiento inexistente. Por eso Contoso no pone el inventario de plazas en Cosmos DB: vive en db-reservas con su restricción CHECK, como se decidió en 03-01. Lo que sí va a Cosmos DB tolera perfectamente la consistencia de sesión, que es el nivel predeterminado y el mejor equilibrio para el 90 % de las aplicaciones.

  1. Distribución global y escrituras multirregión

Añadir una región a una cuenta de Cosmos DB replica todos los datos y permite que los clientes lean del punto más cercano. Hay dos configuraciones muy distintas en coste y en consecuencias:

  • Escrituras en una sola región: una región es la de escritura y las demás son de lectura. Sencillo, sin conflictos posibles y con la mitad de coste.
  • Escrituras multirregión: se puede escribir en cualquier región, con latencia de escritura mínima en todas. El precio es doble: cuesta más por RU y aparecen conflictos cuando dos regiones modifican el mismo documento, que hay que resolver (por defecto gana la última escritura según una marca de tiempo, o con un procedimiento propio).

La decisión de Contoso es coherente con todo el curso: escritura solo en West Europe, lectura también en North Europe. Las tarifas las publica un único equipo desde Barcelona, así que las escrituras multirregión resolverían un problema inexistente a cambio de duplicar la factura y añadir conflictos.

flowchart LR
    subgraph WE[West Europe - escritura]
        C1[(Cosmos DB<br/>region de escritura)]
    end
    subgraph NE[North Europe - solo lectura]
        C2[(Replica de lectura)]
    end
    APP[App Service<br/>Contoso Reservas] -->|escrituras y lecturas| C1
    API[API de Disponibilidad] -->|lecturas| C1
    RESP[Respaldo / informes] -->|lecturas| C2
    C1 -->|replicacion continua| C2

  1. Despliegue con Azure CLI

RG="rg-contoso-reservas-pro"
CUENTA="cosmos-contoso-tarifas-pro"    # minusculas, unico en todo Azure

az cosmosdb create --name $CUENTA --resource-group $RG \
  --locations regionName=westeurope failoverPriority=0 isZoneRedundant=true \
  --locations regionName=northeurope failoverPriority=1 isZoneRedundant=false \
  --default-consistency-level Session \  # equilibrio para el 90 % de los casos
  --enable-multiple-write-locations false \
  --enable-automatic-failover true \
  --backup-policy-type Continuous \
  --tags entorno=produccion proyecto=contoso-reservas centro-coste=CC-1042 [email protected]

az cosmosdb sql database create -a $CUENTA -g $RG -n catalogo

# Contenedor de tarifas: autoescalado hasta 4000 RU/s
az cosmosdb sql container create -a $CUENTA -g $RG -d catalogo -n tarifas \
  --partition-key-path "/origenDestino" \  # DECISION IRREVERSIBLE
  --max-throughput 4000                    # autoescala entre 400 y 4000 RU/s

Para el entorno de desarrollo, la cuenta se crea con --enable-free-tier true (solo una por suscripción) o en modo sin servidor con --capabilities EnableServerless, que no admite autoescalado pero solo cobra lo consumido. Fíjate en que --partition-key-path es el único parámetro de este script que no podrás cambiar después.

  1. Documentos de tarifas: inserción y consulta

Así es un documento de tarifa. Todo lo que en un modelo relacional serían cinco tablas está aquí anidado y se lee de una vez:

{
  "id": "TAR-BCN-CDG-FLEX-2026",
  "origenDestino": "BCN-CDG",
  "tipoTarifa": "flex",
  "moneda": "EUR",
  "precioBase": 214.50,
  "condiciones": {
    "cambiosPermitidos": true,
    "penalizacionCambio": 0,
    "reembolsable": true,
    "equipajeFacturado": { "piezas": 2, "kgPorPieza": 23 }
  },
  "temporadas": [
    { "desde": "2026-06-15", "hasta": "2026-09-15", "recargo": 38.00 },
    { "desde": "2026-12-20", "hasta": "2027-01-07", "recargo": 45.00 }
  ],
  "puntosFidelidad": 850,
  "vigenteHasta": "2026-12-31"
}

Ese mismo documento como filas relacionales exigiría tablas de tarifas, condiciones, equipaje y temporadas, más tres uniones para reconstruirlo. Aquí es una lectura por clave: 1 RU.

az cosmosdb sql container query -a $CUENTA -g $RG -d catalogo -n tarifas \
  --query-text "SELECT * FROM c WHERE c.origenDestino = 'BCN-CDG' AND c.tipoTarifa = 'flex'"

Y las consultas típicas, en el dialecto de la API NoSQL, donde c es cada documento del contenedor:

-- Eficiente: lleva la clave de particion, se resuelve en UNA particion
SELECT c.id, c.precioBase, c.condiciones.equipajeFacturado.piezas
FROM c
WHERE c.origenDestino = 'BCN-CDG' AND c.vigenteHasta >= '2026-08-14';

-- Consulta sobre una propiedad anidada de un array
SELECT c.id, t.recargo
FROM c JOIN t IN c.temporadas
WHERE c.origenDestino = 'BCN-CDG' AND t.desde <= '2026-07-20' AND t.hasta >= '2026-07-20';

-- INEFICIENTE: sin clave de particion, consulta todas las particiones
SELECT * FROM c WHERE c.puntosFidelidad > 500;

El JOIN de la segunda consulta no une contenedores —eso no existe en Cosmos DB—, sino que despliega un array dentro del propio documento. Es la diferencia conceptual que más cuesta a quien viene del mundo relacional.

  1. Política de indexación y tiempo de vida

Por defecto, Cosmos DB indexa todas las propiedades de todos los documentos. Es cómodo al empezar y caro cuando el volumen crece: cada índice consume RU en cada escritura. En un contenedor con escrituras intensas, afinar la política es de los ajustes que más dinero ahorran.

{
  "indexingMode": "consistent",
  "includedPaths": [
    { "path": "/origenDestino/?" },
    { "path": "/tipoTarifa/?" },
    { "path": "/vigenteHasta/?" }
  ],
  "excludedPaths": [
    { "path": "/condiciones/*" },
    { "path": "/temporadas/*" }
  ]
}

Se indexa lo que aparece en cláusulas WHERE u ORDER BY y se excluye lo que solo se lee como parte del documento: las condiciones y las temporadas se devuelven al leer la tarifa, pero nadie filtra por ellas. En los perfiles de pasajero, Contoso aplica el mismo criterio y baja el coste de escritura casi a la mitad.

El tiempo de vida (TTL) borra automáticamente los documentos caducados sin consumir RU de tu contenedor, y es perfecto para datos con vencimiento natural:

# Historial de búsquedas: se elimina solo a los 90 dias (7.776.000 segundos)
az cosmosdb sql container update -a $CUENTA -g $RG -d catalogo -n busquedas \
  --ttl 7776000

Un documento concreto puede sobrescribir ese valor con su propia propiedad ttl, o desactivarlo con ttl: -1.

  1. La fuente de cambios como base de la integración

La fuente de cambios (change feed) es un registro ordenado y persistente de todas las creaciones y modificaciones de un contenedor, que se puede leer en cualquier momento desde el principio o desde un punto guardado. Convierte a Cosmos DB en el punto de partida de arquitecturas basadas en eventos, sin colas adicionales.

En Contoso resuelve tres necesidades reales con el mismo mecanismo: cuando cambia una tarifa, invalidar la caché de la web y avisar al motor de precios; cuando se crea un perfil de pasajero, dispararle el correo de bienvenida; y copiar cada cambio al lago de datos para la analítica del módulo 3.6. Lo habitual es consumirla con un desencadenador de Azure Functions, que gestiona por ti el reparto entre instancias y el punto de lectura guardado; se monta en la lección 06-03. La fuente de cambios no registra los borrados: cuando importa saberlos, se hace un borrado lógico marcando el documento y dejando que el TTL lo elimine después.

  1. Copias de seguridad continuas y control del gasto

Cosmos DB ofrece dos modos de copia de seguridad, y el elegido en el despliegue del apartado 8 es el bueno:

  • Periódicas: instantáneas cada cierto intervalo, con restauración a través de un ticket de soporte. Es el modo antiguo.
  • Continuas (--backup-policy-type Continuous): restauración a cualquier segundo de los últimos 7 o 30 días, ejecutada por ti mismo y a una cuenta nueva, igual que la restauración a un momento dado de Azure SQL Database.
az cosmosdb restore --target-database-account-name cosmos-contoso-tarifas-rec \
  --account-name $CUENTA --restore-timestamp "2026-08-11T16:38:00Z" \
  --location westeurope --resource-group $RG

Sobre el gasto, tres reglas que evitan sustos: el rendimiento aprovisionado factura aunque nadie lea nada, así que un contenedor de pruebas olvidado cuesta dinero cada hora; cada región añadida multiplica el coste de rendimiento y de almacenamiento; y el mínimo de un contenedor con autoescalado es el 10 % del máximo, de modo que fijar 40.000 RU/s de techo implica pagar como mínimo 4000 RU/s siempre. Para dejar de pagar, az cosmosdb delete --name $CUENTA --resource-group $RG --yes, porque una cuenta de Cosmos DB no se puede pausar.

Errores Comunes y Consejos

  • Elegir la clave de partición sin escribir antes las consultas. Es irreversible: corregirla obliga a crear otro contenedor y migrar todo. Escribe primero las cinco consultas más frecuentes.
  • Usar la fecha como clave de partición. Concentra el tráfico reciente en pocas particiones y provoca errores 429 con el contenedor casi ocioso.
  • Consultar sin la clave de partición. Una consulta entre particiones puede costar 20 veces más. Si es inevitable y frecuente, replantea el modelo o crea una vista materializada con la fuente de cambios.
  • Dejar la indexación predeterminada en contenedores con muchas escrituras. Indexarlo todo encarece cada escritura; excluye lo que nunca se filtra.
  • Poner el inventario de plazas en Cosmos DB con consistencia eventual. Se venden asientos que no existen. Ese dato pertenece a la base relacional.
  • Activar escrituras multirregión "por si acaso". Duplica el coste y trae conflictos que hay que resolver. Solo tiene sentido si hay usuarios escribiendo desde varios continentes.
  • Consejo: mira siempre el cargo de RU (x-ms-request-charge) al desarrollar una consulta nueva. Optimizar con esa cifra delante convierte la afinación en algo medible.
  • Consejo: para aprender, activa el nivel gratuito o el modo sin servidor. La diferencia entre una factura de 0 € y una de 300 € es una casilla marcada al crear la cuenta.

Ejercicios

Ejercicio 1: elegir la clave de partición

Contoso añade un contenedor embarques con un documento por pasajero embarcado: unos 90 millones al año, escritos en el momento del escaneo y consultados casi siempre como "todos los embarques de un vuelo concreto en una fecha".

  1. Evalúa como clave de partición /aeropuerto, /fechaEmbarque, /numeroVuelo y una clave sintética /vueloFecha ("CT1042_2026-07-14"), aplicando los tres criterios.
  2. Elige una y justifícala.
  3. ¿Qué política de TTL propondrías y por qué?

Ejercicio 2: consistencia por dato

Para cada dato, elige nivel de consistencia y justifica:

  1. Precio de una tarifa publicada, que cambia dos veces al día.
  2. Preferencia de asiento del pasajero, que él mismo acaba de guardar en la web.
  3. Cupo restante de plazas promocionales de una campaña, con tolerancia de unos segundos.
  4. Historial de estados de una tarifa, donde el orden importa pero el retraso no.

Ejercicio 3: optimizar coste y consultas

Un contenedor perfiles de 5 millones de documentos tiene 20.000 RU/s aprovisionadas fijas, indexación predeterminada, clave de partición /pais y una consulta muy frecuente: SELECT * FROM c WHERE c.correo = @correo.

  1. Identifica los tres problemas.
  2. Propón una corrección para cada uno, indicando cuál exige recrear el contenedor.
  3. ¿Qué modelo de capacidad recomendarías si el tráfico se concentra entre las 8 y las 22 h?

Soluciones

Solución 1:

Candidata Evaluación
/aeropuerto Cardinalidad baja (decenas de aeropuertos) y muy desigual: Barcelona concentraría millones de documentos y chocaría con el límite de 50 GB por partición lógica
/fechaEmbarque Partición caliente clásica: todas las escrituras del día caen en el mismo valor
/numeroVuelo Cardinalidad media y aceptable, pero el mismo número se repite cada día durante años, así que la partición crece sin límite
/vueloFecha Cardinalidad alta, reparto uniforme (cada vuelo-día es un valor distinto), tamaño acotado y aparece en la consulta habitual
  1. /vueloFecha. Es el único candidato que cumple los tres criterios a la vez, y además convierte la consulta más frecuente en una consulta de partición única, de coste mínimo.
  2. TTL de unos 400 días: la explotación operativa necesita el histórico de la temporada y del año anterior; lo más antiguo ya está en el lago de datos para analítica (lección 03-06) y mantenerlo en Cosmos DB solo añade coste de almacenamiento.

Solución 2:

  1. Eventual: es el dato más tolerante del catálogo; que una réplica muestre el precio anterior durante unos segundos no tiene consecuencias, y es el nivel más barato y rápido.
  2. Sesión: el requisito es exactamente "que el cliente vea sus propias escrituras". Con eventual, el pasajero podría guardar su asiento, recargar la página y ver el anterior, que es el fallo que más tickets de soporte genera.
  3. Obsolescencia limitada, acotada por tiempo: garantiza que el desfase no supere unos segundos, suficiente para un cupo promocional donde un pequeño exceso es asumible.
  4. Prefijo coherente: no exige inmediatez, pero impide ver los estados desordenados, que es lo único que rompería la lectura del historial.

Solución 3:

  1. Problemas: (a) la clave de partición /pais tiene cardinalidad bajísima y reparto pésimo —España concentraría la mayoría de los perfiles—; (b) la consulta por correo no lleva la clave de partición, así que se ejecuta contra todas las particiones y cuesta decenas de RU; (c) 20.000 RU/s aprovisionadas fijas se pagan las 24 horas, incluidas las de madrugada, y la indexación predeterminada encarece cada escritura.
  2. Correcciones: cambiar la clave de partición a /correo (o /pasajeroId, si es lo que usa el resto de la aplicación), lo que obliga a crear un contenedor nuevo y migrar los datos, ya que la clave es inmutable; excluir de la indexación las propiedades que nunca se filtran; y pasar a autoescalado.
  3. Autoescalado con un máximo de 20.000 RU/s: por la noche bajará hasta 2000 RU/s (el 10 % del máximo) y solo pagará el pico real de cada hora. Aunque la RU de autoescalado cuesta un 50 % más, con un perfil de 14 horas activas de 24 el ahorro es claro.

Conclusión

Ya tienes las dos mitades del corazón de datos de Contoso Airlines: lo transaccional en Azure SQL Database y lo flexible y global en Azure Cosmos DB. Sabes qué problema resuelve que no resuelve una base relacional —escalado horizontal transparente, latencia garantizada de un dígito en milisegundos y distribución global— y a qué renuncias a cambio: uniones entre entidades y transacciones más allá de una partición. Conoces las cinco API y por qué en un proyecto nuevo se elige la de NoSQL, y manejas la jerarquía de cuenta, base de datos, contenedor y elemento sabiendo que el contenedor es donde se decide todo lo importante.

Sobre todo, has trabajado a fondo la decisión que marca el destino de un proyecto: la clave de partición. Sabes sus tres criterios, por qué /origenDestino funciona para el catálogo de tarifas y por qué /fecha crea una partición caliente que dispara errores 429 con el contenedor ocioso, qué es una clave sintética y por qué corregirse cuesta una migración completa. Entiendes las unidades de solicitud, los cuatro modelos de capacidad y cómo leer el cargo de RU de cada consulta para optimizar con datos y no con intuiciones. Has elegido nivel de consistencia dato a dato con la tabla de los cinco niveles, entendiendo por qué el inventario de plazas se queda en la base relacional y por qué el nivel de sesión es el equilibrio correcto para casi todo. Has desplegado cosmos-contoso-tarifas-pro con lectura en North Europe y escritura solo en West Europe, has insertado y consultado documentos de tarifas viendo la diferencia de coste entre una consulta de partición única y una entre particiones, has afinado la política de indexación, aplicado TTL y conocido la fuente de cambios que alimentará las integraciones del módulo 6, además de las copias continuas y las tres reglas que evitan sustos en la factura.

En la siguiente lección bajamos de las decisiones de diseño a un problema mucho más terrenal y muy frecuente en cualquier migración real. El portal de contenidos y el blog corporativo de Contoso son un WordPress que lleva ocho años funcionando sobre un MySQL instalado en un servidor del sótano de Barcelona, con su versión antigua, sus copias de seguridad en un disco USB y nadie que se atreva a tocarlo. Nadie va a reescribirlo. En Azure Database for MySQL verás cómo se lleva a la nube tal cual: servidor flexible, niveles de cómputo, acceso privado desde la red virtual, parámetros del servidor, réplicas de lectura y, sobre todo, la migración desde el servidor propio con mysqldump o con el servicio de migración de bases de datos, con su checklist de verificación y su ventana de mantenimiento acordada.

Curso de Azure

Módulo 1: Introducción a Azure

Módulo 2: Servicios principales de Azure

Módulo 3: Bases de datos de Azure

Módulo 4: Seguridad en Azure

Módulo 5: Azure DevOps

Módulo 6: Servicios avanzados de Azure

Módulo 7: Monitoreo y gestión

Módulo 8: Gestión y optimización de costos

Módulo 9: Estudios de caso y mejores prácticas

© Copyright 2026. Todos los derechos reservados