La lección anterior terminó con una decisión pendiente. EFS resolvía el problema de que las cuatro
instancias del viernes compartieran /var/www/fotos, pero al precio equivocado: unas trece veces
más caro que la alternativa, con todo el tráfico de imágenes pasando por las instancias y sin
aprovechar la escala global de AWS. Esa alternativa es Amazon S3 (Simple Storage Service), y
esta lección es donde MercadoFresco toma la decisión definitiva sobre sus fotos de producto.
S3 es probablemente el servicio más importante de AWS. Fue el primero que se lanzó, en 2006, y hoy es el sitio donde acaban los datos de casi cualquier arquitectura: ficheros estáticos, copias de seguridad, registros, lagos de datos, artefactos de despliegue. Entenderlo bien —no solo "es donde se suben archivos"— cambia la forma de diseñar sistemas, porque S3 no es un disco: es un almacén de objetos con una API, y esa diferencia tiene consecuencias en todo.
Contenido
- Almacenamiento de objetos: bucket, objeto, clave y prefijo
- Por qué S3 no es un sistema de archivos
- Nombres de bucket, regiones y espacio de nombres global
- Durabilidad y disponibilidad: los once nueves
- Clases de almacenamiento y cómo elegir
- Reglas de ciclo de vida para las fotos antiguas del catálogo
- Versionado y protección frente a borrados accidentales
- Migrar
/var/www/fotosconaws s3 sync aws s3frente aaws s3api- Permisos: Block Public Access, políticas de bucket y ACL
- URLs prefirmadas: los informes de Sara sin credenciales
- Cifrado en reposo y en tránsito
- Alojamiento de un sitio estático
- Eventos de S3: el disparador de las miniaturas
- Multipart upload y Transfer Acceleration
- Costes de S3 y cómo no llevarse sorpresas
Almacenamiento de objetos: bucket, objeto, clave y prefijo
El modelo de S3 tiene solo tres piezas, y conviene nombrarlas con precisión porque toda la documentación las usa así.
| Concepto | Qué es | Ejemplo en MercadoFresco |
|---|---|---|
| Bucket | El contenedor. Vive en una región y tiene nombre único en todo el mundo | mercadofresco-catalogo-fotos |
| Objeto | El dato guardado: contenido + metadatos + identificador | La foto naranjas-valencia-1kg.jpg |
| Clave (key) | El nombre completo del objeto dentro del bucket | productos/frutas/naranjas-valencia-1kg.jpg |
| Prefijo | La parte inicial de la clave, usada para filtrar y organizar | productos/frutas/ |
| Metadatos | Pares clave/valor: tipo de contenido, cifrado, etiquetas | Content-Type: image/jpeg |
Un objeto puede pesar desde 0 bytes hasta 5 TiB. Un bucket puede contener un número ilimitado de objetos y crecer sin que nadie provisione nada.
Por qué S3 no es un sistema de archivos
Esta es la idea que hay que interiorizar, porque de ella se derivan casi todas las sorpresas de los principiantes.
En S3 no existen las carpetas. La consola las dibuja, aws s3 ls las lista, pero no están ahí.
Lo único que existe es una lista plana de claves, y la barra / es un carácter más dentro del
nombre.
Lo que ves en la consola: Lo que hay realmente:
productos/ productos/frutas/naranjas.jpg
├── frutas/ productos/frutas/manzanas.jpg
│ ├── naranjas.jpg productos/verduras/tomates.jpg
│ └── manzanas.jpg informes/2026-07-ventas.csv
└── verduras/
└── tomates.jpg
informes/
└── 2026-07-ventas.csvLas consecuencias prácticas de esto son concretas:
| En un sistema de archivos | En S3 |
|---|---|
| Renombrar una carpeta es instantáneo | Hay que copiar y borrar cada objeto: con 40.000 fotos, 80.000 operaciones |
| Se puede modificar un byte en medio de un fichero | Los objetos son inmutables: se reemplaza el objeto entero |
| Existen carpetas vacías | Una "carpeta vacía" no existe (salvo un objeto de 0 bytes acabado en /) |
mv mueve |
No hay mv real: es copy + delete |
Un open() devuelve un descriptor y lees por partes |
Cada lectura es una petición HTTPS (aunque admite rangos de bytes) |
| La latencia es de microsegundos | Decenas de milisegundos por petición |
Y una consecuencia positiva enorme: al no haber estructura jerárquica real, no hay límite de escala. Un bucket con mil millones de objetos funciona igual de bien que uno con diez, y S3 admite al menos 3.500 escrituras y 5.500 lecturas por segundo y por prefijo, con paralelización prácticamente ilimitada usando varios prefijos.
Por eso el diseño de claves importa. Para MercadoFresco:
productos/frutas/naranjas-valencia-1kg.jpg # original productos/frutas/naranjas-valencia-1kg_thumb.jpg # miniatura (la generará Lambda, 02-05) informes/2026/07/ventas-julio.csv # informes de Sara, particionados por fecha copias/base-datos/2026-08-02-pedidos.dump # copias
Nombres de bucket, regiones y espacio de nombres global
El nombre de un bucket es único en todo AWS, en todas las cuentas y todas las regiones del
mundo. Si alguien en Australia tiene fotos, tú no puedes tenerlo. Es el único recurso de AWS con
espacio de nombres verdaderamente global.
Reglas del nombre:
- Entre 3 y 63 caracteres.
- Solo minúsculas, números, guiones y puntos.
- Debe empezar y acabar con letra o número.
- No puede parecerse a una dirección IP.
- Evita los puntos: rompen la validación del certificado TLS con nombres de estilo virtual y causan errores difíciles de diagnosticar.
Convención de MercadoFresco, que aplicaremos siempre:
mercadofresco-<componente>-<proposito>[-<entorno>] mercadofresco-catalogo-fotos mercadofresco-informes-analitica mercadofresco-copias-basedatos mercadofresco-tienda-web-desarrollo
Aunque el nombre sea global, los datos residen en una región concreta y nunca salen de ella
salvo que lo pidas explícitamente. Para MercadoFresco esto no es un detalle: las fotos y los
informes se quedan en eu-west-1, dentro de la UE, lo que sostiene el argumento de RGPD que vimos
en 01-03.
aws s3api create-bucket \
--bucket mercadofresco-catalogo-fotos \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1 \
--profile mercadofresco-dev
# Etiquetado obligatorio del proyecto
aws s3api put-bucket-tagging \
--bucket mercadofresco-catalogo-fotos \
--tagging 'TagSet=[
{Key=Proyecto,Value=mercadofresco},
{Key=Entorno,Value=produccion},
{Key=Componente,Value=catalogo},
{Key=Propietario,Value=luis},
{Key=CentroCoste,Value=marketing}]' \
--profile mercadofresco-dev --region eu-west-1La trampa de
LocationConstraint. Enus-east-1(y solo ahí) no debe pasarse ese parámetro: el comando falla si lo incluyes. En cualquier otra región es obligatorio. Es una herencia histórica de que S3 nació en Virginia.
Durabilidad y disponibilidad: los once nueves
S3 Standard promete 99,999999999 % de durabilidad anual: los famosos once nueves. La cifra suena a marketing, pero tiene un significado operativo preciso.
Si guardas 10 millones de objetos, la expectativa estadística es perder uno cada 10.000 años. Dicho de otro modo: es muchísimo más probable que pierdas los datos por un borrado accidental o una política mal escrita que por un fallo de S3.
Cómo se consigue: cada objeto se replica automáticamente en al menos tres zonas de disponibilidad de la región, con verificación continua de integridad y reparación automática. Tú no configuras nada.
No hay que confundir dos métricas distintas:
| Métrica | Qué mide | S3 Standard | Consecuencia si falla |
|---|---|---|---|
| Durabilidad | Que el dato no se pierda | 99,999999999 % | Pérdida permanente |
| Disponibilidad | Que puedas acceder ahora | 99,99 % (≈53 min/año) | Errores temporales; se reintenta |
Un matiz que importa mucho para MercadoFresco: la durabilidad de S3 no te protege de ti mismo.
Si Luis ejecuta un aws s3 rm --recursive sobre el bucket equivocado, S3 lo borrará con once nueves
de fiabilidad. La protección contra eso es el versionado, que veremos más abajo.
Clases de almacenamiento y cómo elegir
No todos los datos se acceden igual. Las fotos de los tomates de temporada se piden mil veces al día en junio y ninguna en enero. S3 ofrece clases con distinto equilibrio entre coste de almacenamiento y coste/latencia de acceso.
| Clase | Coste GB-mes (eu-west-1, aprox.) |
Latencia de recuperación | Coste de recuperación | AZ | Mínimo de permanencia | Caso de uso |
|---|---|---|---|---|---|---|
| Standard | 0,023 USD | Milisegundos | No | ≥3 | Ninguno | Datos activos: fotos del catálogo actual |
| Intelligent-Tiering | 0,023 → 0,0025 USD | Milisegundos | No (pequeña cuota de monitorización) | ≥3 | Ninguno | Patrón de acceso desconocido o cambiante |
| Standard-IA | 0,0125 USD | Milisegundos | Sí, por GB | ≥3 | 30 días | Acceso mensual, se necesita rápido |
| One Zone-IA | 0,01 USD | Milisegundos | Sí, por GB | 1 | 30 días | Copias reproducibles, miniaturas regenerables |
| Glacier Instant Retrieval | 0,004 USD | Milisegundos | Sí, mayor | ≥3 | 90 días | Archivo consultado un par de veces al año |
| Glacier Flexible Retrieval | 0,0036 USD | Minutos a 12 horas | Sí | ≥3 | 90 días | Copias de seguridad de cumplimiento |
| Glacier Deep Archive | 0,00099 USD | 12 a 48 horas | Sí, el mayor | ≥3 | 180 días | Retención legal de 7 o 10 años |
Entre Standard y Deep Archive hay un factor de 23 veces en el coste de almacenamiento. Ese es el premio por clasificar bien los datos.
Tres criterios de decisión:
- Si no sabes el patrón de acceso, usa Intelligent-Tiering. Mueve los objetos entre niveles automáticamente, sin coste de recuperación, cobrando una pequeña cuota de monitorización por objeto. Es la opción segura por defecto para datos heterogéneos.
- Cuidado con el mínimo de permanencia. Si subes un objeto a Standard-IA y lo borras a los 10 días, se te cobran los 30. Para datos de vida corta, esta clase sale más cara que Standard.
- One Zone-IA solo para datos reproducibles. Vive en una sola AZ: si esa AZ se pierde, el dato se pierde. Es perfecto para las miniaturas de MercadoFresco, porque siempre se pueden regenerar a partir del original.
Reglas de ciclo de vida para las fotos antiguas del catálogo
Una regla de ciclo de vida aplica transiciones y caducidades automáticamente según la edad de los objetos. Es la forma de que el ahorro anterior ocurra sin que nadie intervenga.
El análisis de MercadoFresco: las fotos de producto se consultan intensamente los primeros meses
tras publicarse, luego el interés cae, y las de productos descatalogados solo se necesitan por
motivos contables. Traducido a política, en ciclo-vida-fotos.json:
{
"Rules": [
{
"ID": "fotos-productos-enfriamiento",
"Filter": {"Prefix": "productos/"},
"Status": "Enabled",
"Transitions": [
{"Days": 90, "StorageClass": "STANDARD_IA"},
{"Days": 365, "StorageClass": "GLACIER_IR"},
{"Days": 1095,"StorageClass": "DEEP_ARCHIVE"}
]
},
{
"ID": "miniaturas-una-sola-az",
"Filter": {"Prefix": "miniaturas/"},
"Status": "Enabled",
"Transitions": [
{"Days": 30, "StorageClass": "ONEZONE_IA"}
]
},
{
"ID": "informes-analitica-caducan-a-2-anos",
"Filter": {"Prefix": "informes/"},
"Status": "Enabled",
"Transitions": [
{"Days": 60, "StorageClass": "STANDARD_IA"}
],
"Expiration": {"Days": 730}
},
{
"ID": "limpiar-cargas-multiparte-incompletas",
"Filter": {},
"Status": "Enabled",
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
},
{
"ID": "versiones-antiguas-caducan-a-90-dias",
"Filter": {},
"Status": "Enabled",
"NoncurrentVersionExpiration": {"NoncurrentDays": 90}
}
]
}aws s3api put-bucket-lifecycle-configuration \
--bucket mercadofresco-catalogo-fotos \
--lifecycle-configuration file://ciclo-vida-fotos.json \
--profile mercadofresco-dev --region eu-west-1Comentario regla por regla:
fotos-productos-enfriamiento: escalera de tres saltos. A los 3 meses baja a IA, al año a Glacier Instant (que sigue devolviendo en milisegundos), a los 3 años a Deep Archive.miniaturas-una-sola-az: aprovecha que son regenerables. Ahorro sin riesgo real.informes-analitica-caducan-a-2-anos: además de mover, borra. Los informes de Sara no tienen valor pasados dos años y borrar es el ahorro definitivo.limpiar-cargas-multiparte-incompletas: la más olvidada y la que más dinero silencioso ahorra. Una subida grande interrumpida deja fragmentos que se facturan y no aparecen al listar el bucket. Esta regla debería estar en absolutamente todos tus buckets.versiones-antiguas-caducan-a-90-dias: sin esto, el versionado hace crecer el bucket para siempre.
Estimación del ahorro para 40.000 fotos de 500 KB (unos 20 GB) con una distribución de edades típica:
| Escenario | Coste mensual |
|---|---|
| Todo en Standard | 20 GB × 0,023 = 0,46 USD |
| Con ciclo de vida (5 GB Standard, 8 GB IA, 7 GB Glacier IR) | 0,115 + 0,10 + 0,028 = 0,24 USD |
Con 20 GB la diferencia es calderilla. Con los 20 TB que MercadoFresco tendrá tras abrir en tres ciudades más (problema 3), son más de 250 USD al mes de diferencia. Las reglas se ponen ahora, cuando cuestan un minuto, no cuando duelen.
Versionado y protección frente a borrados accidentales
Con el versionado activado, S3 nunca sobrescribe ni borra de verdad:
- Al subir un objeto con una clave existente, se crea una versión nueva y la anterior se conserva.
- Al borrar, se coloca un marcador de borrado (delete marker): el objeto desaparece de los listados pero todas sus versiones siguen ahí.
- Para recuperarlo basta con borrar el marcador de borrado.
aws s3api put-bucket-versioning \
--bucket mercadofresco-catalogo-fotos \
--versioning-configuration Status=Enabled \
--profile mercadofresco-dev --region eu-west-1Recuperación de un borrado accidental, el escenario real:
# 1. Luis borra una foto por error
aws s3 rm s3://mercadofresco-catalogo-fotos/productos/frutas/naranjas.jpg \
--profile mercadofresco-dev
# 2. Ya no aparece al listar... pero sigue existiendo
aws s3api list-object-versions \
--bucket mercadofresco-catalogo-fotos \
--prefix productos/frutas/naranjas.jpg \
--query '{Versiones:Versions[].[VersionId,LastModified],Marcadores:DeleteMarkers[].[VersionId]}' \
--profile mercadofresco-dev --region eu-west-1
# 3. Se borra el MARCADOR DE BORRADO (no la versión) y la foto reaparece
aws s3api delete-object \
--bucket mercadofresco-catalogo-fotos \
--key productos/frutas/naranjas.jpg \
--version-id "3HL4kqCxf3vjVBH40Nrjfkd" \
--profile mercadofresco-dev --region eu-west-1Una vez activado, el versionado no se puede desactivar, solo suspender (las versiones ya creadas
se conservan). Y ojo al coste: cada versión se factura por separado, de ahí la regla de ciclo de
vida NoncurrentVersionExpiration del apartado anterior.
Dos protecciones adicionales, mencionadas brevemente porque son de casos concretos:
- MFA Delete: exige un código de autenticación multifactor del usuario root para borrar versiones o cambiar el estado del versionado. Muy fuerte, pero solo se activa con las credenciales de root y no se puede gestionar desde la consola, lo que lo hace incómodo para el día a día.
- Object Lock (WORM: write once, read many): impide borrar o modificar un objeto durante un periodo fijado, incluso al administrador de la cuenta. Tiene dos modos, Governance (un rol con permiso especial puede saltárselo) y Compliance (nadie puede, ni el root). Es para retención legal. Solo se puede activar al crear el bucket. Para las copias de la base de datos de MercadoFresco tendría sentido; para las fotos, no.
Migrar /var/www/fotos con aws s3 sync
Llega el momento. Las 40.000 fotos del servidor de la oficina se van a S3.
# Ensayo en seco: muestra qué haría SIN hacer nada. Hazlo siempre primero.
aws s3 sync /var/www/fotos s3://mercadofresco-catalogo-fotos/productos/ \
--dryrun \
--profile mercadofresco-dev
# Migración real
aws s3 sync /var/www/fotos s3://mercadofresco-catalogo-fotos/productos/ \
--storage-class STANDARD \
--exclude "*" \
--include "*.jpg" --include "*.jpeg" --include "*.png" --include "*.webp" \
--metadata-directive REPLACE \
--cache-control "public, max-age=86400" \
--profile mercadofresco-devQué hace cada opción:
synces incremental: compara tamaño y fecha de modificación, y solo sube lo que ha cambiado. Se puede interrumpir y relanzar sin duplicar trabajo, que es justo lo que se necesita para migrar 40.000 ficheros por una conexión de oficina.--dryrun: imprescindible antes de cualquiersynccon destino nuevo.--exclude "*"seguido de varios--include: el orden importa. Primero se excluye todo y después se readmiten las extensiones deseadas. Así no se cuelan.DS_Store,Thumbs.dbni copias.bak.--cache-control: se guarda como metadato y lo respetarán los navegadores y, más adelante, CloudFront (03-04). Un día de caché para fotos que casi nunca cambian.
Verificación tras la migración:
# Número de ficheros en origen
find /var/www/fotos -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.webp" \) | wc -l
# Número de objetos y tamaño total en destino
aws s3 ls s3://mercadofresco-catalogo-fotos/productos/ --recursive --summarize \
--human-readable --profile mercadofresco-dev | tail -3Para volúmenes muy grandes hay opciones específicas que conviene conocer aunque no las usemos:
AWS DataSync para transferencias masivas y recurrentes por red, y la familia AWS Snowball
para cuando mover los datos por internet tardaría más que enviarlos físicamente en un dispositivo.
Para los 20 GB de MercadoFresco, sync sobra.
aws s3 frente a aws s3api
La CLI ofrece dos interfaces distintas para S3, y confundirlas provoca mucha frustración.
aws s3 |
aws s3api |
|
|---|---|---|
| Qué es | Comandos de alto nivel, estilo Unix | Correspondencia 1:1 con las operaciones de la API |
| Comandos | ls, cp, mv, rm, sync, mb, rb, presign |
put-object, get-object, list-object-versions, put-bucket-policy… |
| Multipart automático | Sí, para ficheros grandes | No, hay que orquestarlo a mano |
| Recursividad | --recursive |
Hay que paginar |
| Control fino | Limitado | Total: cualquier parámetro de la API |
| Cuándo usarlo | Día a día: copiar, sincronizar, listar | Configurar el bucket, versiones, políticas, ACL |
Regla práctica: mueve datos con aws s3, configura con aws s3api.
# Alto nivel: cómodo y suficiente el 90 % del tiempo
aws s3 cp informe.csv s3://mercadofresco-informes-analitica/informes/2026/07/ \
--profile mercadofresco-dev
aws s3 ls s3://mercadofresco-catalogo-fotos/productos/frutas/ --profile mercadofresco-dev
# Bajo nivel: cuando hace falta un parámetro que el alto nivel no expone
aws s3api put-object \
--bucket mercadofresco-informes-analitica \
--key informes/2026/07/ventas.csv \
--body informe.csv \
--server-side-encryption aws:kms \
--content-type text/csv \
--tagging "Proyecto=mercadofresco&Componente=analitica&Propietario=sara" \
--profile mercadofresco-dev --region eu-west-1Permisos: Block Public Access, políticas de bucket y ACL
Las filtraciones de datos por buckets S3 mal configurados han sido titular de prensa muchas veces. AWS respondió cambiando los valores por defecto: hoy todo bucket nuevo nace completamente privado y con Block Public Access activado a nivel de cuenta y de bucket.
# Verificar el estado (debe dar true en las cuatro opciones)
aws s3api get-public-access-block \
--bucket mercadofresco-catalogo-fotos \
--profile mercadofresco-dev --region eu-west-1{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}Los cuatro interruptores, que mucha gente activa o desactiva sin saber qué hace cada uno:
| Opción | Qué impide |
|---|---|
BlockPublicAcls |
Que se creen ACL públicas nuevas |
IgnorePublicAcls |
Que las ACL públicas existentes surtan efecto |
BlockPublicPolicy |
Que se añada una política de bucket que conceda acceso público |
RestrictPublicBuckets |
Que una política pública ya existente funcione para usuarios anónimos |
La postura de MercadoFresco es dejar Block Public Access activado en todos los buckets, sin excepción. Las fotos se servirán públicamente a través de CloudFront con un control de acceso de origen, no abriendo el bucket. Eso se monta en la lección 03-04.
Políticas de bucket
Una política de bucket es un documento JSON de IAM adjunto al bucket que dice quién puede hacer qué. Ejemplo real de MercadoFresco: permitir que solo el rol de las instancias de la tienda lea las fotos, y obligar a que todo el tráfico use HTTPS.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PermitirLecturaAlRolDeLaTienda",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/rol-mercadofresco-tienda"
},
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::mercadofresco-catalogo-fotos",
"arn:aws:s3:::mercadofresco-catalogo-fotos/*"
]
},
{
"Sid": "DenegarTodoLoQueNoSeaHTTPS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mercadofresco-catalogo-fotos",
"arn:aws:s3:::mercadofresco-catalogo-fotos/*"
],
"Condition": {
"Bool": {"aws:SecureTransport": "false"}
}
}
]
}aws s3api put-bucket-policy \
--bucket mercadofresco-catalogo-fotos \
--policy file://politica-bucket-fotos.json \
--profile mercadofresco-dev --region eu-west-1Dos detalles fundamentales:
s3:ListBucketse concede sobre el bucket (arn:aws:s3:::bucket), mientras ques3:GetObjectse concede sobre los objetos (arn:aws:s3:::bucket/*). Son ARN distintos y confundirlos es el error de política más frecuente.- Un
Denyexplícito gana siempre sobre cualquierAllow, venga de donde venga. Por eso la segunda instrucción es una defensa sólida: nadie, ni el administrador, puede acceder por HTTP sin cifrar. La lógica completa de evaluación de permisos es la lección 04-01.
ACL: legado
Las ACL (Access Control Lists) son el mecanismo original de 2006, anterior a IAM. Conceden permisos objeto a objeto a cuentas o grupos predefinidos.
AWS recomienda no usarlas. Desde 2023, los buckets nuevos nacen con Object Ownership en
"Bucket owner enforced", que las desactiva por completo. Solo debes conocerlas para dos cosas:
reconocerlas al heredar una cuenta antigua, y saber que si un tutorial te dice --acl public-read,
ese tutorial está desactualizado. Usa políticas de bucket.
URLs prefirmadas: los informes de Sara sin credenciales
Sara, la analista de negocio, necesita descargar el informe mensual de ventas. No tiene usuario de AWS, no debe tenerlo, y el bucket es privado. La solución es una URL prefirmada: un enlace temporal que incorpora una firma criptográfica y caduca.
"""
Genera una URL temporal de descarga para un informe de MercadoFresco.
Ejecutar con el perfil mercadofresco-dev configurado (lección 01-05).
"""
import boto3
from botocore.exceptions import ClientError
BUCKET = "mercadofresco-informes-analitica"
REGION = "eu-west-1"
def url_de_descarga(clave: str, segundos: int = 3600) -> str | None:
"""Devuelve una URL prefirmada de descarga, o None si algo falla.
:param clave: clave del objeto, p. ej. 'informes/2026/07/ventas-julio.csv'
:param segundos: validez del enlace. Máximo 7 días con credenciales de usuario.
"""
# La firma v4 exige que el cliente conozca la región del bucket.
s3 = boto3.session.Session(profile_name="mercadofresco-dev").client(
"s3", region_name=REGION
)
try:
return s3.generate_presigned_url(
ClientMethod="get_object",
Params={"Bucket": BUCKET, "Key": clave},
ExpiresIn=segundos,
)
except ClientError as e:
print(f"No se pudo generar la URL: {e}")
return None
def url_de_subida(clave: str, segundos: int = 900) -> dict | None:
"""URL prefirmada de SUBIDA, con condiciones que limitan lo que se puede subir.
Se usa para que un proveedor externo suba fotos de producto sin tener
credenciales de AWS ni acceso al resto del bucket.
"""
s3 = boto3.session.Session(profile_name="mercadofresco-dev").client(
"s3", region_name=REGION
)
try:
return s3.generate_presigned_post(
Bucket="mercadofresco-catalogo-fotos",
Key=clave,
Fields={"Content-Type": "image/jpeg"},
Conditions=[
{"Content-Type": "image/jpeg"}, # solo JPEG
["content-length-range", 1024, 5242880], # entre 1 KB y 5 MB
],
ExpiresIn=segundos,
)
except ClientError as e:
print(f"No se pudo generar la URL de subida: {e}")
return None
if __name__ == "__main__":
enlace = url_de_descarga("informes/2026/07/ventas-julio.csv", segundos=3600)
print(f"Enlace para Sara (válido 1 hora):\n{enlace}")Lo esencial de este mecanismo:
- Quien tenga el enlace puede usarlo. No hay autenticación adicional: el enlace es la credencial. Por eso los plazos deben ser cortos.
- La URL hereda los permisos de quien la firma. Si el perfil que firma no puede leer el objeto, la URL tampoco funcionará.
- Caducidad máxima: 7 días con credenciales de usuario IAM; 1 hora si se firma desde un rol con credenciales temporales, como sería el caso dentro de una Lambda.
generate_presigned_postconConditionses la forma correcta de aceptar subidas de terceros: limita tipo y tamaño antes de que el fichero llegue.
Cifrado en reposo y en tránsito
Todo objeto nuevo en S3 se cifra en reposo automáticamente desde enero de 2023. No hay que hacer nada para tener cifrado; la decisión es solo quién gestiona la clave.
| Modo | Quién gestiona la clave | Coste extra | Auditoría del uso de la clave | Cuándo |
|---|---|---|---|---|
SSE-S3 (AES256) |
AWS, de forma transparente | Ninguno | No | Valor por defecto; suficiente casi siempre |
SSE-KMS (aws:kms) |
Tú, en AWS KMS | Sí, por clave y por petición | Sí, en CloudTrail | Datos regulados, separación de funciones |
| SSE-C | Tú, enviando la clave en cada petición | Ninguno en AWS | No | Requisitos muy específicos |
| DSSE-KMS | Doble cifrado con KMS | Mayor | Sí | Requisitos gubernamentales |
Decisión de MercadoFresco: SSE-S3 para las fotos (son datos públicos en la práctica, no compensa el coste por petición de KMS) y SSE-KMS para los informes de ventas y las copias de la base de datos, que contienen datos de negocio y donde interesa el registro de quién descifra.
# Forzar SSE-KMS por defecto en el bucket de informes
aws s3api put-bucket-encryption \
--bucket mercadofresco-informes-analitica \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "alias/mercadofresco-datos"
},
"BucketKeyEnabled": true
}]
}' \
--profile mercadofresco-dev --region eu-west-1BucketKeyEnabled: true reduce hasta un 99 % las llamadas a KMS y su coste asociado; actívalo
siempre que uses SSE-KMS. La gestión de claves se ve a fondo en la lección 04-02.
En tránsito, todo el tráfico con S3 va por HTTPS. Para garantizar que nadie use HTTP en claro
está la instrucción DenegarTodoLoQueNoSeaHTTPS de la política de bucket anterior.
Alojamiento de un sitio estático
S3 puede servir un sitio web estático directamente: HTML, CSS, JavaScript e imágenes, sin ningún servidor.
aws s3 website s3://mercadofresco-tienda-web-desarrollo/ \
--index-document index.html \
--error-document error.html \
--profile mercadofresco-devEl resultado es una URL del tipo
http://mercadofresco-tienda-web-desarrollo.s3-website-eu-west-1.amazonaws.com.
Limitaciones que hay que conocer antes de emocionarse:
- Solo HTTP, sin HTTPS. El punto de enlace de sitio web estático no admite TLS.
- Sin dominio propio con certificado.
- Exige el bucket público, lo que choca con la política de Block Public Access.
Por eso, en producción no se usa así. La arquitectura correcta es bucket privado + CloudFront delante con Origin Access Control: da HTTPS, dominio propio, caché en más de 400 ubicaciones de borde y protección. Eso es exactamente la lección 03-04. El modo sitio web de S3 queda para pruebas rápidas de Luis.
Eventos de S3: el disparador de las miniaturas
S3 puede notificar cuando pasa algo en un bucket. Es la puerta de entrada a las arquitecturas orientadas a eventos, y para MercadoFresco resuelve un problema concreto: las fotos originales pesan demasiado para el listado de productos y hacen falta miniaturas.
Eventos disponibles y destinos posibles:
| Tipo de evento | Cuándo se dispara |
|---|---|
s3:ObjectCreated:* |
Cualquier creación (Put, Post, Copy, fin de multipart) |
s3:ObjectRemoved:* |
Borrado o marcador de borrado |
s3:ObjectRestore:* |
Restauración desde Glacier completada |
s3:LifecycleTransition |
Un objeto ha cambiado de clase por una regla de ciclo de vida |
s3:ReducedRedundancyLostObject |
Pérdida de un objeto (clase obsoleta) |
| Destino | Cuándo elegirlo |
|---|---|
| AWS Lambda | Procesar el objeto con código propio: nuestro caso |
| Amazon SQS | Encolar para procesamiento en lotes o con reintentos (módulo 7) |
| Amazon SNS | Notificar a varios suscriptores a la vez (módulo 7) |
| EventBridge | Enrutado avanzado con reglas y filtros (módulo 7) |
El flujo que montaremos:
flowchart LR
A["Luis sube<br/>naranjas.jpg"] --> B["Bucket<br/>mercadofresco-catalogo-fotos<br/>prefijo productos/"]
B -->|"s3:ObjectCreated:*"| C["Notificacion de evento"]
C --> D["Funcion Lambda<br/>mercadofresco-generar-miniaturas"]
D --> E["Escribe en<br/>prefijo miniaturas/<br/>200x200 px"]
E -.->|"regla de ciclo de vida"| F["ONEZONE_IA a los 30 dias"]
Configuración de la notificación (la función se escribe en 02-05):
aws s3api put-bucket-notification-configuration \
--bucket mercadofresco-catalogo-fotos \
--notification-configuration '{
"LambdaFunctionConfigurations": [{
"Id": "generar-miniaturas-al-subir",
"LambdaFunctionArn": "arn:aws:lambda:eu-west-1:111122223333:function:mercadofresco-generar-miniaturas",
"Events": ["s3:ObjectCreated:*"],
"Filter": {"Key": {"FilterRules": [
{"Name": "prefix", "Value": "productos/"},
{"Name": "suffix", "Value": ".jpg"}
]}}
}]
}' \
--profile mercadofresco-dev --region eu-west-1El filtro por prefijo y sufijo es imprescindible. Sin él, la Lambda se dispararía también al escribir las miniaturas en el mismo bucket, que a su vez generarían otro evento: un bucle recursivo infinito que es una de las formas más rápidas y más caras de equivocarse en AWS.
Dos advertencias sobre la semántica de estos eventos: la entrega es al menos una vez (la función puede recibir el mismo evento dos veces, así que debe ser idempotente) y no está garantizado el orden. Aquí solo dejamos montado el disparador; el código lo escribimos en la lección 02-05.
Multipart upload y Transfer Acceleration
Multipart upload trocea un objeto grande y sube las partes en paralelo. Es obligatorio por encima de 5 GB y recomendable a partir de 100 MB.
Ventajas: mayor rendimiento por paralelismo, reintento de una sola parte si falla la red, y
posibilidad de pausar y reanudar. aws s3 cp y aws s3 sync lo hacen automáticamente; solo
necesitas s3api si programas el proceso a mano.
# Ajustar los umbrales de la CLI para una conexión rápida
aws configure set default.s3.multipart_threshold 64MB
aws configure set default.s3.multipart_chunksize 16MB
aws configure set default.s3.max_concurrent_requests 20El riesgo: si una subida multiparte se interrumpe, las partes ya subidas se quedan y se
facturan, y no aparecen en un aws s3 ls normal. Por eso incluimos la regla
AbortIncompleteMultipartUpload en el ciclo de vida. Para verlas:
aws s3api list-multipart-uploads --bucket mercadofresco-catalogo-fotos \
--profile mercadofresco-dev --region eu-west-1Transfer Acceleration enruta las subidas a través de la ubicación de borde de CloudFront más cercana al cliente, y de ahí por la red troncal de AWS hasta el bucket. Acelera de forma significativa cuando quien sube está lejos de la región. Tiene coste adicional (≈0,04 USD/GB) y para MercadoFresco, que sube desde España a Irlanda, no compensa. Sería útil si un proveedor de Sudamérica subiera catálogos de fotos.
# Comprobar si merecería la pena, con la herramienta de comparación de AWS:
# https://s3-accelerate-speedtest.s3-accelerate.amazonaws.com/en/accelerate-speed-comparsion.html
aws s3api put-bucket-accelerate-configuration \
--bucket mercadofresco-catalogo-fotos --accelerate-configuration Status=Enabled \
--profile mercadofresco-dev --region eu-west-1Costes de S3 y cómo no llevarse sorpresas
La factura de S3 tiene cuatro componentes, y casi todo el mundo solo mira el primero.
| Componente | Precio orientativo (eu-west-1) |
Comentario |
|---|---|---|
| Almacenamiento | 0,023 USD/GB-mes (Standard) | El más visible y a menudo el menor |
| Peticiones | PUT: 0,0054 USD por 1.000 GET: 0,00043 USD por 1.000 |
Domina el coste con muchos objetos pequeños |
| Transferencia de salida | 0,09 USD/GB hacia internet | Suele ser el mayor. Entrada gratis; salida a otra región, también de pago |
| Recuperación y gestión | Variable por clase | Recuperar de Glacier, monitorización de Intelligent-Tiering, inventario |
Cálculo realista para MercadoFresco: 20 GB de fotos, 500.000 visitas al mes con 10 fotos vistas por visita (5.000.000 de peticiones GET), foto media de 200 KB:
Almacenamiento: 20 GB × 0,023 = 0,46 USD
Peticiones GET: 5.000.000 / 1.000 × 0,00043 = 2,15 USD
Transferencia: 5.000.000 × 200 KB = 1.000 GB
1.000 GB × 0,09 = 90,00 USD
------------------------------------------------------------------
Total ≈ 92,61 USD/mesEl 97 % del coste es transferencia de salida. Y ese dato justifica por sí solo la lección 03-04: poniendo CloudFront delante, la mayoría de las peticiones se sirven desde la caché de borde, la transferencia de S3 a CloudFront es gratuita, y el precio por GB hacia internet es menor. La factura puede bajar a menos de una tercera parte, y además la web irá más rápida.
Herramientas de control:
# Tamaño y número de objetos por bucket
aws s3 ls s3://mercadofresco-catalogo-fotos --recursive --summarize --human-readable \
--profile mercadofresco-dev | tail -3- S3 Storage Lens ofrece un panel gratuito con métricas de uso y recomendaciones de ahorro.
- S3 Inventory genera un informe periódico en CSV o Parquet con todos los objetos, su clase y su tamaño: la forma correcta de auditar buckets con millones de objetos sin listarlos uno a uno.
- El presupuesto
presupuesto-mensual-mercadofrescode la lección 01-02 sigue siendo la red de seguridad.
Limpieza de la lección. Si has creado buckets de prueba, elimínalos. Un bucket con versionado requiere borrar también las versiones y los marcadores:
aws s3 rm s3://mi-bucket-de-pruebas --recursive --profile mercadofresco-dev aws s3api delete-objects --bucket mi-bucket-de-pruebas \\ --delete "$(aws s3api list-object-versions --bucket mi-bucket-de-pruebas \\ --query '{Objects: Versions[].{Key:Key,VersionId:VersionId}}' --output json)" \\ --profile mercadofresco-dev aws s3 rb s3://mi-bucket-de-pruebas --profile mercadofresco-dev
Errores Comunes y Consejos
- Tratar S3 como un disco. Renombrar un prefijo con 40.000 objetos son 80.000 operaciones y minutos de espera. Diseña las claves bien desde el principio.
- Hacer un bucket público "para que funcione rápido". Es el origen de la mayoría de las filtraciones publicadas. Deja Block Public Access activado y usa CloudFront con OAC.
- Olvidar
LocationConstraintfuera deus-east-1, o ponerlo dentro deus-east-1. Ambos fallan, con mensajes poco claros. - No configurar
AbortIncompleteMultipartUpload. Coste invisible que crece para siempre. - Activar el versionado y no caducar las versiones antiguas. El bucket engorda sin límite y nadie entiende por qué la factura sube si "no se sube nada nuevo".
- Confundir el ARN del bucket con el de los objetos en las políticas:
ListBucketva sobre el bucket,GetObjectsobrebucket/*. - Poner una Lambda a escuchar eventos del mismo bucket donde escribe. Bucle infinito. Filtra siempre por prefijo, o usa buckets distintos.
- Usar
--acl public-readporque lo dice un tutorial antiguo. Las ACL están desactivadas por defecto en buckets nuevos y AWS desaconseja su uso. - Subir a Standard-IA datos de vida corta. El mínimo de 30 días de facturación hace que salga más caro que Standard.
- Mirar solo el coste de almacenamiento. La transferencia de salida suele ser el 90 % de la factura de S3.
- Consejo: ejecuta
synccon--dryrunsiempre la primera vez. Un destino mal escrito puede copiar 40.000 ficheros al prefijo equivocado, y deshacerlo es más trabajo que hacerlo.
Ejercicios
Ejercicio 1: diseñar el ciclo de vida de las copias de la base de datos
MercadoFresco guardará en mercadofresco-copias-basedatos los volcados diarios de la base de datos
de pedidos, bajo el prefijo copias/base-datos/. Cada volcado ocupa 2 GB. Los requisitos son:
- Los últimos 30 días deben poder restaurarse en minutos.
- Entre 30 días y 1 año, la restauración puede tardar horas.
- Entre 1 y 7 años (retención legal fiscal) se conservan al coste mínimo posible.
- Pasados 7 años se borran automáticamente.
Escribe la regla de ciclo de vida en JSON y calcula el coste mensual en régimen estacionario, comparándolo con dejarlo todo en Standard. Usa: Standard 0,023; Glacier Flexible 0,0036; Deep Archive 0,00099 USD/GB-mes.
Ejercicio 2: la política de bucket de los informes
Sara debe poder leer los informes bajo informes/, pero no borrarlos ni tocar otros prefijos.
El rol rol-mercadofresco-analitica debe poder escribir en informes/. Nadie debe acceder sin
HTTPS ni subir objetos sin cifrar con KMS.
Escribe la política de bucket completa y explica por qué la última condición necesita un Deny y no
un Allow.
Ejercicio 3: decidir dónde va cada dato
Para cada dato de MercadoFresco, indica bucket, prefijo, clase de almacenamiento inicial, si activas versionado y qué regla de ciclo de vida aplicarías:
- A) Las 40.000 fotos originales del catálogo, en alta resolución.
- B) Las miniaturas 200×200 generadas automáticamente a partir de las anteriores.
- C) Los registros de acceso del servidor web, unos 3 GB al día, consultados solo si hay una incidencia y obligatorios durante 90 días.
- D) El informe mensual de ventas que Sara descarga por URL prefirmada.
Soluciones
Solución 1.
{
"Rules": [
{
"ID": "copias-base-datos-retencion-fiscal",
"Filter": {"Prefix": "copias/base-datos/"},
"Status": "Enabled",
"Transitions": [
{"Days": 30, "StorageClass": "GLACIER"},
{"Days": 365, "StorageClass": "DEEP_ARCHIVE"}
],
"Expiration": {"Days": 2555}
},
{
"ID": "limpiar-multipart",
"Filter": {},
"Status": "Enabled",
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
}
]
}Volumen en régimen estacionario (2 GB/día):
Standard (0-30 días): 30 × 2 GB = 60 GB Glacier Flexible (30-365): 335 × 2 GB = 670 GB Deep Archive (365-2555): 2190 × 2 GB = 4.380 GB Total = 5.110 GB
| Configuración | Cálculo | Coste mensual |
|---|---|---|
| Con ciclo de vida | 60×0,023 + 670×0,0036 + 4.380×0,00099 | 8,13 USD |
| Todo en Standard | 5.110 × 0,023 | 117,53 USD |
| Ahorro | 109,40 USD/mes (93 %) |
Notas de diseño: 2.555 días son 7 años. Deep Archive tiene 180 días de permanencia mínima, sin problema aquí porque los objetos llegan con 365 días de vida y se quedan más de seis años. Y el requisito "restaurar en minutos los últimos 30 días" es lo que impide bajar a Glacier antes: Glacier Flexible tarda de minutos a 12 horas según el modo de recuperación.
Solución 2.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SaraLeeInformes",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111122223333:user/sara"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mercadofresco-informes-analitica/informes/*"
},
{
"Sid": "SaraListaSoloElPrefijoInformes",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111122223333:user/sara"},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mercadofresco-informes-analitica",
"Condition": {"StringLike": {"s3:prefix": "informes/*"}}
},
{
"Sid": "RolAnaliticaEscribeInformes",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111122223333:role/rol-mercadofresco-analitica"},
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::mercadofresco-informes-analitica/informes/*"
},
{
"Sid": "DenegarSinHTTPS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mercadofresco-informes-analitica",
"arn:aws:s3:::mercadofresco-informes-analitica/*"
],
"Condition": {"Bool": {"aws:SecureTransport": "false"}}
},
{
"Sid": "DenegarSubidasSinCifradoKMS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mercadofresco-informes-analitica/*",
"Condition": {
"StringNotEquals": {"s3:x-amz-server-side-encryption": "aws:kms"}
}
}
]
}Por qué las dos últimas necesitan Deny y no Allow. Un Allow solo concede: si simplemente
"permitieras HTTPS", cualquier otra política —una política de identidad de IAM adjunta al usuario,
por ejemplo— podría seguir concediendo el acceso por HTTP, porque los permisos se suman. Un
Deny explícito, en cambio, tiene precedencia absoluta: ninguna política de ninguna capa puede
anularlo. Para requisitos de seguridad que deben cumplirse siempre y sin excepción, la
formulación correcta es prohibir la condición indeseada, no permitir la deseada.
Detalle adicional: sin la condición s3:prefix en ListBucket, Sara podría listar todo el bucket y
ver los nombres de objetos de otros prefijos, aunque no pudiera descargarlos. Nombres que a veces
revelan más de lo que parece.
Solución 3.
| Dato | Bucket y prefijo | Clase inicial | Versionado | Ciclo de vida |
|---|---|---|---|---|
| A) Fotos originales | mercadofresco-catalogo-fotos / productos/ |
Standard | Sí: son el original y no se pueden regenerar; protege del rm accidental |
IA a 90 d, Glacier IR a 365 d, Deep Archive a 3 años; versiones antiguas caducan a 90 d |
| B) Miniaturas | mercadofresco-catalogo-fotos / miniaturas/ |
Standard, y One Zone-IA a los 30 d | No: son regenerables con la Lambda; el versionado solo añadiría coste | A One Zone-IA a los 30 d. Prefijo distinto del origen para no crear bucle de eventos |
| C) Registros del servidor web | mercadofresco-registros-web / nginx/AAAA/MM/DD/ |
Standard | No | IA a 30 d, caducidad a 90 d exactamente (el requisito legal). Particionar por fecha en la clave facilita consultarlos y borrarlos |
| D) Informe mensual de ventas | mercadofresco-informes-analitica / informes/AAAA/MM/ |
Standard con SSE-KMS | Sí: es un dato de negocio que no debe perderse por sobrescritura | IA a 60 d, caducidad a 2 años. Acceso solo por URL prefirmada, bucket privado |
Observación transversal: el prefijo de las miniaturas debe estar fuera del prefijo que dispara
el evento (productos/), o el filtro de la notificación debe excluirlas. Es la protección contra el
bucle recursivo mencionado antes.
Conclusión
MercadoFresco ya tiene sus fotos donde deben estar. Has entendido que S3 es un almacén de objetos y no un sistema de archivos: no hay carpetas, solo claves planas donde la barra es un carácter más; los objetos son inmutables; renombrar un prefijo significa copiar y borrar. A cambio de esas restricciones se obtiene escala prácticamente ilimitada, once nueves de durabilidad por replicación automática en tres o más zonas de disponibilidad, y un coste por GB unas trece veces menor que EFS.
Sabes construir nombres de bucket válidos en un espacio de nombres global, con la trampa de
LocationConstraint incluida, y tienes una convención propia (mercadofresco-<componente>- <propósito>). Dominas las siete clases de almacenamiento y sus compensaciones —latencia, coste
de recuperación, permanencia mínima, número de AZ— y has escrito reglas de ciclo de vida que
enfrían las fotos del catálogo automáticamente, mueven las miniaturas a One Zone-IA por ser
regenerables, caducan los informes a los dos años, borran las versiones antiguas y —la regla que
todo el mundo olvida— abortan las cargas multiparte incompletas que se facturan en silencio.
Has activado el versionado y practicado la recuperación real de un borrado accidental eliminando
el marcador de borrado, y conoces MFA Delete y Object Lock para los casos que exigen
retención inviolable. Has migrado /var/www/fotos con aws s3 sync, con su --dryrun
obligatorio y sus filtros de inclusión, y tienes clara la división de trabajo entre aws s3
para mover datos y aws s3api para configurar.
En seguridad, has visto por qué hoy los buckets nacen cerrados: Block Public Access con sus
cuatro interruptores, políticas de bucket en JSON con la distinción crítica entre el ARN del
bucket y el de los objetos, la precedencia absoluta del Deny explícito, y las ACL como legado
que no debes usar. Has generado URLs prefirmadas con boto3 para que Sara descargue sus informes
sin tener credenciales de AWS, y también para aceptar subidas de terceros con límites de tipo y
tamaño. Sabes que todo se cifra en reposo por defecto y cuándo compensa pasar de SSE-S3 a
SSE-KMS con BucketKeyEnabled.
Has visto el alojamiento estático y por qué no se usa así en producción, has dejado configurada la notificación de eventos que disparará la generación de miniaturas —con el filtro por prefijo que evita el bucle infinito—, conoces multipart upload y Transfer Acceleration, y has hecho el cálculo que ordena todo lo demás: en la factura de S3 de MercadoFresco, el 97 % es transferencia de salida, no almacenamiento.
Quedan las fotos resueltas y falta el corazón del negocio. Los pedidos de MercadoFresco siguen en la base de datos del servidor de la oficina, con su copia de seguridad poco fiable y su imposibilidad de crecer. En la lección 02-04, «Amazon RDS», migraremos esa base de datos a un servicio gestionado: veremos qué aporta frente a instalar PostgreSQL en una EC2, montaremos Multi-AZ con réplica síncrona en espera, crearemos réplicas de lectura para que los informes de Sara no castiguen a producción, y cerraremos definitivamente el problema 2 con copias automáticas y restauración a un punto en el tiempo.
Curso de AWS
Módulo 1: Introducción a AWS
- ¿Qué es AWS?
- Configuración de tu cuenta de AWS
- Infraestructura global de AWS
- Consola de administración de AWS
- AWS CLI y SDKs
Módulo 2: Servicios principales de AWS
Módulo 3: Redes y entrega de contenido
- Amazon VPC
- Grupos de seguridad y listas de control de acceso
- Elastic Load Balancing
- Amazon CloudFront
- Route 53
Módulo 4: Seguridad e identidad
- AWS Identity and Access Management (IAM)
- AWS Key Management Service (KMS)
- Secrets Manager y Parameter Store
- AWS Shield
- AWS WAF
Módulo 5: Monitorización y gestión
- Amazon CloudWatch
- AWS X-Ray y trazabilidad distribuida
- AWS CloudTrail
- AWS Config
- AWS Trusted Advisor
Módulo 6: Bases de datos
- Cómo elegir la base de datos adecuada
- Amazon DynamoDB
- Amazon Aurora
- Amazon Redshift
- Amazon ElastiCache
Módulo 7: Integración de aplicaciones
- Amazon SQS
- Amazon SNS
- Amazon EventBridge
- AWS Step Functions
- Patrones de integración: idempotencia, reintentos y colas de mensajes fallidos
