Objetivo
Decidir el tipo de almacenamiento correcto para cada componente de una tienda online y aprovisionarlo usando AWS CDK, entendiendo las diferencias entre almacenamiento de objetos, en bloque, relacional y NoSQL.
Contexto
Una tienda online necesita almacenar tres tipos de datos con características muy distintas:
- Imágenes de productos: archivos de gran tamaño, acceso frecuente, no estructurados.
- Catálogo de productos: datos estructurados con relaciones (categorías, precios, inventario).
- Órdenes de compra: escrituras de alta frecuencia, acceso por
orderIdocustomerId, esquema flexible.
Cada tipo de dato tiene requisitos distintos. Usar el servicio equivocado impacta el costo y el rendimiento.
Requisitos
- S3: bucket para imágenes de productos (con lifecycle policy para mover a S3-IA imágenes de más de 90 días).
- RDS (PostgreSQL): base de datos relacional para el catálogo de productos (tablas:
products,categories,inventory). - DynamoDB: tabla NoSQL para órdenes de compra (clave de partición:
customerId, clave de ordenamiento:orderId). - EBS: volumen de bloque para almacenamiento temporal de procesamiento de órdenes en una instancia EC2.
- Todo definido con CDK. Ningún recurso debe crearse manualmente.
Servicios AWS
| Servicio | Tipo | Uso en la tienda |
|---|---|---|
| S3 | Object Storage | Imágenes de productos |
| RDS | Relational DB | Catálogo y relaciones |
| DynamoDB | NoSQL | Órdenes de alta frecuencia |
| EBS | Block Storage | Procesamiento temporal |
Infrastructure as Code (AWS CDK)
$ cdk init app --language typescript
$ cdk synth
$ cdk deploy
Fragmento clave:
// lib/store-backend-stack.ts
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
// S3 para imágenes
const imagesBucket = new s3.Bucket(this, 'ProductImagesBucket', {
lifecycleRules: [{
transitions: [{
storageClass: s3.StorageClass.INFREQUENT_ACCESS,
transitionAfter: cdk.Duration.days(90),
}],
}],
});
// DynamoDB para órdenes
const ordersTable = new dynamodb.Table(this, 'OrdersTable', {
partitionKey: { name: 'customerId', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'orderId', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
});
Entregables
- Bucket S3 con lifecycle policy configurada en el stack CDK.
- Instancia RDS PostgreSQL en subnet privada (no accesible públicamente).
- Tabla DynamoDB con
customerIdcomo PK yorderIdcomo SK. - Justificación escrita de por qué se eligió cada servicio para cada tipo de dato.
-
cdk deployexitoso sin recursos creados manualmente.
Criterios de Éxito
- Los cuatro tipos de almacenamiento están creados y accesibles.
- RDS no tiene una IP pública asignada.
- La lifecycle policy de S3 está configurada correctamente.
- La tabla DynamoDB puede recibir escrituras con la estructura definida.
Boss Fight
La tienda creció de 10,000 a 1,000,000 de clientes. El equipo de producto pide soportar este volumen sin rediseñar la arquitectura.
¿Qué cambia?
- DynamoDB ya escala automáticamente (
PAY_PER_REQUEST), pero debes habilitar DynamoDB Streams para procesar eventos de órdenes en tiempo real. - RDS necesita una Read Replica para distribuir las lecturas del catálogo.
- El bucket S3 necesita replicación cross-region para garantizar disponibilidad global.
- Actualiza tu stack CDK para reflejar estos cambios sin recrear los recursos existentes.
Cleanup
$ cdk destroy
⚠️ RDS puede tardar varios minutos en eliminarse. Si tienes una Read Replica, debes eliminarla antes que la instancia principal.
