Base de Datos Relacional
Este generador crea un nuevo proyecto de base de datos relacional respaldado por Amazon Aurora (PostgreSQL o MySQL) y Prisma ORM. Genera el código de aplicación y la infraestructura necesaria para aprovisionar y gestionar una base de datos usando AWS CDK o Terraform, con definición de esquema declarativa, despliegue automático de migraciones y un cliente ORM con tipos seguros.
Generar una Base de Datos Relacional
Sección titulada «Generar una Base de Datos Relacional»Puedes generar un nuevo proyecto de base de datos relacional de dos maneras:
- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - ts#rdb - Complete los parámetros requeridos
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:ts#rdbyarn nx g @aws/nx-plugin:ts#rdbnpx nx g @aws/nx-plugin:ts#rdbbunx nx g @aws/nx-plugin:ts#rdbTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#rdb --dry-runyarn nx g @aws/nx-plugin:ts#rdb --dry-runnpx nx g @aws/nx-plugin:ts#rdb --dry-runbunx nx g @aws/nx-plugin:ts#rdb --dry-runOpciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| name Requerido | string | - | Nombre del proyecto de base de datos a generar |
| directory | string | packages | El directorio donde almacenar la aplicación. |
| subDirectory | string | - | El subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto. |
| service Requerido | string | Aurora | Servicio de base de datos relacional a aprovisionar. |
| engine Requerido | string | PostgreSQL | Motor de base de datos a utilizar con el servicio seleccionado. |
| databaseUser | string | dbadmin | Nombre de usuario del administrador de la base de datos. Por defecto es 'dbadmin'. |
| databaseName | string | - | Nombre inicial de la base de datos. Por defecto es el nombre del proyecto. |
| ormFramework Requerido | string | Prisma | Framework ORM a utilizar para el proyecto generado. |
| iacProvider | string | Inherit | El proveedor IaC preferido. Por defecto se hereda de tu selección inicial. |
Salida del Generador
Sección titulada «Salida del Generador»El generador creará la siguiente estructura de proyecto en el directorio <directory>/<name>:
Directorioprisma
Directoriomodels
- example.prisma Definición de modelo de ejemplo
- schema.prisma Esquema principal de Prisma (referencia modelos)
Directorioscripts
- docker-pull.ts Descarga la imagen Docker de la base de datos para desarrollo local
- docker-start.ts Inicia un contenedor de base de datos local
- wait-for-db.ts Espera a que la base de datos local esté lista
Directoriosrc
- index.ts Punto de entrada del proyecto
- constants.ts Detalles de conexión de desarrollo local y clave de configuración en tiempo de ejecución
- prisma.ts Envoltorio del cliente Prisma en tiempo de ejecución
- utils.ts Ayudantes de configuración en tiempo de ejecución y secretos
- create-db-user-handler.ts Manejador Lambda usado para crear el usuario de base de datos de aplicación durante el despliegue
- migration-handler.ts Manejador Lambda usado para ejecutar migraciones de base de datos durante el despliegue
- .gitignore Entradas de Git ignore incluyendo la salida del cliente Prisma generado
- Dockerfile Definición de imagen de contenedor para el manejador de migración
- project.json Configuración del proyecto y objetivos de construcción
- prisma.config.ts Configuración para Prisma CLI
Infraestructura
Sección titulada «Infraestructura»Dado que este generador proporciona infraestructura como código basada en tu proveedor de iacProvider seleccionado, creará un proyecto en packages/common que incluye los constructos CDK o módulos de Terraform correspondientes.
El proyecto común de infraestructura como código tiene la siguiente estructura:
Directoriopackages/common/constructs
Directoriosrc
Directorioapp/ Constructos para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Constructos genéricos reutilizados por los constructos en
app- …
- index.ts Punto de entrada que exporta los constructos de
app
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/terraform
Directoriosrc
Directorioapp/ Módulos de Terraform para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Módulos genéricos reutilizados por los módulos en
app- …
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/constructs/src
Directorioapp
Directoriodbs
- <name>.ts Infraestructura específica para tu base de datos
Directoriocore
Directoriordb
- aurora.ts Constructo genérico de base de datos Aurora
Directoriopackages/common/terraform/src
Directorioapp
Directoriodbs
Directorio<name>
- <name>.tf Módulo específico para tu base de datos
Directoriocore
Directoriordb
Directorioaurora
- aurora.tf Módulo genérico Aurora
Desarrollo Local
Sección titulada «Desarrollo Local»Modelado de Datos
Sección titulada «Modelado de Datos»El proyecto generado usa Prisma ORM para definir tu esquema de base de datos y generar un cliente con tipos seguros. El flujo de trabajo es model-first: agrega o actualiza archivos de modelo Prisma bajo el directorio prisma/models/ de tu proyecto de base de datos, luego genera una migración a partir de esos cambios de modelo.
Ejemplo de modelo User:
model User { id Int @id @default(autoincrement()) firstName String lastName String}Para más detalles, consulta la guía oficial de modelado de datos con Prisma.
Generando el Cliente de Base de Datos
Sección titulada «Generando el Cliente de Base de Datos»El generador configura automáticamente el objetivo generate para crear un cliente TypeScript de Prisma con tipos seguros cada vez que construyes el proyecto. El cliente se escribe en generated/prisma (agregado a .gitignore).
También puedes generar manualmente el cliente en cualquier momento:
pnpm nx generate <your-db-project-name>yarn nx generate <your-db-project-name>npx nx generate <your-db-project-name>bunx nx generate <your-db-project-name>Usa el objetivo prisma para ejecutar comandos de Prisma CLI desde la raíz del workspace:
pnpm nx run <project>:prisma generateyarn nx run <project>:prisma generatenpx nx run <project>:prisma generatebunx nx run <project>:prisma generateEl envoltorio en tiempo de ejecución en src/prisma.ts exporta:
DB_PACKAGE_NAME- la clave usada bajo el espacio de nombres de configuración en tiempo de ejecucióndatabaseen AWS AppConfiggetPrisma()- carga la configuración de conexión de base de datos desde AWS AppConfig y crea un cliente Prisma usando autenticación IAM
El cliente automáticamente:
- Recupera la configuración de base de datos desde AWS AppConfig usando la variable de entorno
RUNTIME_CONFIG_APP_ID - Genera tokens de autenticación temporales a través de AWS RDS Signer para autenticación IAM
- Gestiona conexiones SSL/TLS con validación de certificados
- Maneja el pooling de conexiones a través de pools de conexión de base de datos persistentes
Creando Migraciones
Sección titulada «Creando Migraciones»Después de agregar o actualizar modelos bajo prisma/models/, usa migrate dev para generar archivos de migración y aplicarlos a tu base de datos local al mismo tiempo.
El objetivo prisma generado automáticamente inicia una base de datos local a través de Docker antes de ejecutar:
pnpm nx run <project>:prisma migrate devyarn nx run <project>:prisma migrate devnpx nx run <project>:prisma migrate devbunx nx run <project>:prisma migrate devSi solo deseas generar los archivos de migración sin aplicarlos a la base de datos local, agrega --create-only:
pnpm nx run <project>:prisma migrate dev --create-onlyyarn nx run <project>:prisma migrate dev --create-onlynpx nx run <project>:prisma migrate dev --create-onlybunx nx run <project>:prisma migrate dev --create-onlyEsto genera una nueva carpeta de migración en prisma/migrations cada vez que tu esquema cambia:
Directorioprisma
Directoriomigrations
Directorio20260405013911_initial_migrations
- migration.sql
- migration_lock.toml
- schema.prisma
Cuando despliegas el stack de AWS, la infraestructura generada aplica automáticamente las migraciones generadas a la base de datos desplegada.
Aplicando Migraciones Existentes
Sección titulada «Aplicando Migraciones Existentes»Cuando obtienes archivos de migración creados por otros desarrolladores, usa migrate deploy para aplicar esas migraciones existentes a tu base de datos local.
pnpm nx run <project>:prisma migrate deployyarn nx run <project>:prisma migrate deploynpx nx run <project>:prisma migrate deploybunx nx run <project>:prisma migrate deployEn este flujo de desarrollo local, migrate deploy aplica los archivos de migración a tu base de datos local; no despliega la base de datos en AWS.
Ejecutando Comandos de Prisma
Sección titulada «Ejecutando Comandos de Prisma»El objetivo prisma generado expone la CLI de Prisma, por lo que puedes usarlo para ejecutar cualquier comando soportado por Prisma contra la base de datos local. Consulta la referencia de CLI de Prisma para los comandos disponibles.
pnpm nx run <project>:prisma <prisma-command>yarn nx run <project>:prisma <prisma-command>npx nx run <project>:prisma <prisma-command>bunx nx run <project>:prisma <prisma-command>Prisma Studio
Sección titulada «Prisma Studio»Prisma Studio es un editor visual para tu base de datos local. Úsalo para explorar tablas, inspeccionar y editar registros, filtrar datos, seguir relaciones y ejecutar SQL sin procesar a través de la consola SQL integrada. Es útil para verificar migraciones y sembrar datos de prueba durante el desarrollo. Inícialo con:
pnpm nx run <project>:prisma studioyarn nx run <project>:prisma studionpx nx run <project>:prisma studiobunx nx run <project>:prisma studioConectando desde una API tRPC
Sección titulada «Conectando desde una API tRPC»Aunque esta sección describe cómo conectarse a tu base de datos desde una API tRPC, también sirve como referencia para su uso en cualquier otro proyecto TypeScript.
Usando el Cliente Prisma en Manejadores
Sección titulada «Usando el Cliente Prisma en Manejadores»Importa getPrisma desde tu paquete de base de datos y llámalo dentro de tu manejador para obtener un cliente Prisma con tipos seguros:
import { getPrisma } from ':my-scope/db';import { publicProcedure } from '../init.js';import { ListUsersOutputSchema } from '../schema/index.js';
export const listUsers = publicProcedure .output(ListUsersOutputSchema) .query(async () => { const prisma = await getPrisma(); return prisma.user.findMany({ orderBy: { id: 'asc' } }); });getPrisma() devuelve un cliente inicializado de forma perezosa y en caché. Las llamadas subsiguientes dentro del mismo contexto de ejecución Lambda reutilizan el pool de conexiones existente en lugar de abrir uno nuevo.
El cliente Prisma expone modelos completamente tipados derivados de tu esquema prisma/models/, brindándote seguridad de tipos de extremo a extremo desde la base de datos hasta la respuesta de tu API.
Inyectando el Cliente Prisma a través de Middleware
Sección titulada «Inyectando el Cliente Prisma a través de Middleware»En lugar de llamar getPrisma() en cada procedimiento, también puedes resolverlo una vez en un middleware y adjuntarlo al contexto tRPC para que todos los procedimientos posteriores puedan acceder a él directamente.
Primero, define el plugin en src/middleware/db.ts siguiendo el mismo patrón que el middleware generado:
import { getPrisma } from ':my-scope/db';import { initTRPC } from '@trpc/server';
export interface IDbContext { db: Awaited<ReturnType<typeof getPrisma>>;}
export const createDbPlugin = () => { const t = initTRPC.context<IDbContext>().create(); return t.procedure.use(async (opts) => { const db = await getPrisma(); return opts.next({ ctx: { ...opts.ctx, db, }, }); });};Luego concaténalo a un procedimiento base en tu inicialización tRPC:
import { createDbPlugin } from './middleware/db.js';
export const dbProcedure = publicProcedure.concat(createDbPlugin());Los procedimientos construidos sobre dbProcedure reciben db a través del contexto sin necesidad de importar o llamar getPrisma() ellos mismos:
import { dbProcedure } from '../init.js';import { ListUsersOutputSchema } from '../schema/index.js';
export const listUsers = dbProcedure .output(ListUsersOutputSchema) .query(async ({ ctx: { db } }) => { return db.user.findMany({ orderBy: { id: 'asc' } }); });Desplegando tu Base de Datos
Sección titulada «Desplegando tu Base de Datos»El generador de base de datos relacional crea infraestructura CDK o Terraform basándose en tu iacProvider seleccionado.
El constructo CDK se crea en common/constructs. Ejemplo de uso:
import { MyDatabase } from ':my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); ... const db = new MyDatabase(this, 'Db', { vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_ISOLATED, } }); }}Esto aprovisiona un clúster Aurora con RDS Proxy, credenciales de administrador, usuario de base de datos de aplicación, registro de configuración en tiempo de ejecución y manejador de migración.
La infraestructura generada crea dos usuarios de base de datos:
- Usuario administrador - Creado durante el aprovisionamiento del clúster con credenciales almacenadas en AWS Secrets Manager
- Usuario de aplicación - Creado a través de un recurso personalizado Lambda con autenticación IAM habilitada y privilegios completos en la base de datos de aplicación
El módulo Terraform se crea en common/terraform. Ejemplo de uso:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
vpc_id = module.vpc.vpc_id database_subnet_ids = module.vpc.private_isolated_subnet_ids lambda_subnet_ids = module.vpc.private_subnet_ids
tags = local.common_tags}Esto aprovisiona un clúster Aurora con RDS Proxy, credenciales de administrador, Lambda create-db-user, registro de configuración en tiempo de ejecución, Lambda de migración y recursos de registro de contenedor.
La infraestructura generada crea dos usuarios de base de datos:
- Usuario administrador - Creado durante el aprovisionamiento del clúster con credenciales almacenadas en AWS Secrets Manager
- Usuario de aplicación - Creado a través de una función Lambda con autenticación IAM habilitada y privilegios completos en la base de datos de aplicación
El usuario de aplicación se crea automáticamente con un nombre aleatorio y autenticación IAM. getPrisma() ya está configurado para autenticarse como este usuario usando tokens RDS de corta duración, por lo que tu código de aplicación nunca maneja contraseñas de base de datos.
Tu VPC debe incluir subredes públicas, subredes privadas con egreso y subredes privadas aisladas. La base de datos puede ejecutarse en subredes privadas aisladas, mientras que las funciones Lambda de la API deben ejecutarse en subredes privadas con egreso para que puedan alcanzar servicios de AWS como AppConfig.
const vpc = new Vpc(this, 'Vpc', { subnetConfiguration: [ { name: 'public', subnetType: SubnetType.PUBLIC, }, { name: 'private_with_egress', subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, { name: 'private_isolated', subnetType: SubnetType.PRIVATE_ISOLATED, }, ],});module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 6.0"
name = "app" ... public_subnet_names = ["public"] private_subnet_names = ["private_with_egress"] intra_subnet_names = ["private_isolated"]
enable_nat_gateway = true single_nat_gateway = true}Conectando una API a la Base de Datos
Sección titulada «Conectando una API a la Base de Datos»En tu stack de aplicación, despliega la API en la misma VPC que la base de datos, luego llama a allowDefaultPortFrom y grantConnect para abrir la ruta de red y otorgar permiso IAM rds-db:connect a cada manejador Lambda:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { vpc, ... });
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this) .withDefaultOptions({ vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS }, }) .build(),});
Object.entries(api.integrations).forEach(([operation, integration]) => { db.allowDefaultPortFrom(integration.handler, `Allow ${operation} to connect to the database`); db.grantConnect(integration.handler);});Despliega las funciones Lambda de la API en una subred privada con egreso (recomendado) o una subred pública, no en una subred privada aislada. En tiempo de ejecución, getPrisma() recupera los detalles de conexión de base de datos desde AWS AppConfig, que es un endpoint de servicio público de AWS. Las funciones Lambda en una subred privada aislada no tienen acceso saliente a internet y no pueden alcanzar AppConfig. Las subredes privadas con egreso enrutan el tráfico saliente a través de un NAT Gateway que se encuentra en una subred pública.
Pasa las salidas del módulo de base de datos a tu módulo de cómputo para que pueda alcanzar la base de datos y leer su configuración en tiempo de ejecución:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" vpc_id = module.vpc.vpc_id database_subnet_ids = module.vpc.private_isolated_subnet_ids lambda_subnet_ids = module.vpc.private_subnet_ids}
module "api" { source = "..." vpc_id = module.vpc.vpc_id private_subnet_ids = module.vpc.private_subnet_ids
# Permitir que la API lea la configuración en tiempo de ejecución desde AppConfig appconfig_application_id = module.my_database.appconfig_application_id
# Otorgar rds-db:connect para el usuario de base de datos de aplicación database_cluster_resource_id = module.my_database.cluster_resource_id database_runtime_user = module.my_database.database_runtime_user
# Permitir acceso de red al puerto de la base de datos database_security_group_id = module.my_database.security_group_id database_port = module.my_database.cluster_port
environment_variables = { RUNTIME_CONFIG_APP_ID = module.my_database.appconfig_application_id }}Despliega las funciones Lambda de la API en subredes privadas con egreso (recomendado) o subredes públicas, no en subredes privadas aisladas. En tiempo de ejecución, getPrisma() recupera los detalles de conexión de base de datos desde AWS AppConfig, que es un endpoint de servicio público de AWS. Las funciones Lambda en una subred privada aislada no tienen acceso saliente a internet y no pueden alcanzar AppConfig. Las subredes privadas con egreso enrutan el tráfico saliente a través de un NAT Gateway que requiere una subred pública.
Asegúrate de que el rol Lambda de la API tenga rds-db:connect en arn:aws:rds-db:<region>:<account>:dbuser:<cluster_resource_id>/<database_runtime_user> y permisos de lectura de AppConfig, que el grupo de seguridad de la API pueda alcanzar el grupo de seguridad de la base de datos en el puerto de la base de datos, y que el entorno Lambda incluya RUNTIME_CONFIG_APP_ID.
Configuración de RDS Proxy
Sección titulada «Configuración de RDS Proxy»La infraestructura generada incluye un RDS Proxy por defecto, que se sitúa entre tu aplicación y el clúster Aurora. RDS Proxy proporciona varios beneficios:
- Connection pooling - Mantiene un pool de conexiones de base de datos que pueden compartirse entre instancias de aplicación, reduciendo la sobrecarga de establecer nuevas conexiones
- Resiliencia de conexión - Maneja automáticamente failovers y reconexiones durante reemplazos o mantenimiento de instancias Aurora
- Autenticación IAM - Soporta autenticación de base de datos basada en IAM, eliminando la necesidad de gestionar credenciales de base de datos en tu código de aplicación
- Seguridad mejorada - Impone cifrado TLS para todas las conexiones
Deshabilitar RDS Proxy
Sección titulada «Deshabilitar RDS Proxy»Puedes deshabilitar el proxy RDS de la siguiente manera:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});Cuando RDS Proxy está deshabilitado, tu aplicación se conecta directamente al endpoint del clúster Aurora.
Para conexiones directas al clúster Aurora desde runtimes Lambda de Node.js 20 o posterior, configura la función Lambda para cargar el paquete CA de Amazon RDS:
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this) .withDefaultOptions({ environment: { NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem', }, }) .build(),});Por defecto, RDS Proxy está habilitado. El cliente en tiempo de ejecución generado (getPrisma()) se conecta automáticamente a través del endpoint del proxy. Puedes deshabilitarlo si es necesario:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}Cuando RDS Proxy está deshabilitado, tu aplicación se conecta directamente al endpoint del clúster Aurora.
Para conexiones directas al clúster Aurora desde runtimes Lambda de Node.js 20 o posterior, configura la función Lambda para cargar el paquete CA de Amazon RDS:
module "api" { source = "..." ...
environment_variables = { NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem" }}Para más detalles, consulta los requisitos SSL/TLS de AWS Lambda para conexiones Amazon RDS y la documentación TLS de Amazon RDS Proxy. Al usar RDS Proxy, no necesitas configurar el paquete CA de RDS en tu función Lambda.
La infraestructura generada puede personalizarse para coincidir con los requisitos de tu carga de trabajo. Los siguientes ejemplos demuestran algunas opciones de personalización comunes disponibles.
Instancias del Clúster
Sección titulada «Instancias del Clúster»Configura las instancias writer y reader para tu clúster Aurora.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... writer: ClusterInstance.serverlessV2('writer'), readers: [ClusterInstance.serverlessV2('reader')],});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... instance_count = 2 # 1 writer + 1 reader}Capacidad Serverless
Sección titulada «Capacidad Serverless»Controla los límites de escalado de Aurora Serverless v2 para coincidir con tu carga de trabajo.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... serverlessV2MinCapacity: 0.5, serverlessV2MaxCapacity: 8,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... serverless_min_capacity = 0.5 serverless_max_capacity = 8}Versión del Motor
Sección titulada «Versión del Motor»Fija una versión específica del motor Aurora.
Por defecto, la imagen Docker de base de datos local generada coincide con la versión del motor Aurora predeterminada. Si cambias la versión del motor Aurora, se recomienda usar también una versión de base de datos Docker local coincidente para máxima compatibilidad. Consulta las notas de lanzamiento de AWS para versiones de Aurora PostgreSQL y versiones de Aurora MySQL para identificar la versión de base de datos comunitaria correspondiente.
La imagen de base de datos local se configura en el objetivo serve-local del proyecto de base de datos generado en project.json. Actualiza el argumento de imagen pasado a scripts/docker-start.ts cuando cambies las versiones del motor.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraPostgresEngineVersion.VER_17_7,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "17.7"}import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "8.0.mysql_aurora.3.12.0"}Protección contra Eliminación
Sección titulada «Protección contra Eliminación»La protección contra eliminación está habilitada por defecto (deletionProtection: true en CDK, deletion_protection = true en Terraform) para proteger el clúster Aurora de eliminación accidental.
Deshabilitar Protección contra Eliminación
Sección titulada «Deshabilitar Protección contra Eliminación»Puedes deshabilitar la protección contra eliminación para entornos donde se espera la eliminación de la base de datos, como stacks de desarrollo o vista previa de corta duración.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false}Política de Eliminación
Sección titulada «Política de Eliminación»El constructo CDK retiene el clúster Aurora por defecto (removalPolicy: RemovalPolicy.RETAIN). Cambia esto cuando desees que la eliminación del stack CDK haga una instantánea o destruya el clúster en su lugar.
Cuando uses RemovalPolicy.DESTROY, la protección contra eliminación también debe deshabilitarse antes de que el clúster pueda ser eliminado.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});Para un entorno efímero donde la base de datos debe eliminarse con el stack:
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});Terraform no usa políticas de eliminación de CDK. Por defecto, el módulo crea una instantánea final al eliminar (skip_final_snapshot = false). Para omitir la instantánea final en un entorno efímero:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}Rotación de Clave de Cifrado
Sección titulada «Rotación de Clave de Cifrado»La clave KMS utilizada para cifrar el clúster Aurora y su secreto de credenciales tiene habilitada la rotación automática de claves por defecto. Deshabilítala si tu política de seguridad gestiona la rotación externamente.
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableKeyRotation: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_key_rotation = false}Limitaciones
Sección titulada «Limitaciones»MySQL: Modo de Streaming de API Gateway
Sección titulada «MySQL: Modo de Streaming de API Gateway»Al usar Aurora MySQL con respuestas de streaming de API Gateway (por ejemplo, con httpBatchStreamLink de tRPC), el cliente MySQL de Prisma retiene el bucle de eventos de Node.js después de que se completa una consulta, evitando que Lambda vacíe el stream y finalice la solicitud.
Para solucionar esto, desconecta explícitamente el cliente en un bloque finally después de cada consulta para que el bucle de eventos esté libre para salir y la respuesta de streaming pueda completarse.
Opción 1: por procedimiento
export const listExampleTable = publicProcedure .output(z.array(ExampleTableSchema)) .query(async () => { const prisma = await getPrisma(); try { return await prisma.exampleTable.findMany(); } finally { await prisma.$disconnect(); } });Opción 2: middleware de tRPC
Si estás usando el patrón de middleware, agrega la llamada $disconnect() al middleware para que todos los procedimientos construidos sobre él estén cubiertos automáticamente:
import { getPrisma } from ':my-scope/db';import { initTRPC } from '@trpc/server';
export interface IDbContext { db: Awaited<ReturnType<typeof getPrisma>>;}
export const createDbPlugin = () => { const t = initTRPC.context<IDbContext>().create(); return t.procedure.use(async (opts) => { const db = await getPrisma(); try { return await opts.next({ ctx: { ...opts.ctx, db, }, }); } finally { await db.$disconnect(); } });};MySQL: Expiración de Token IAM
Sección titulada «MySQL: Expiración de Token IAM»Los tokens de autenticación IAM de RDS expiran después de 15 minutos. El cliente Prisma de MySQL captura el token IAM como un valor estático en el momento en que se llama a getPrisma(). Una conexión abierta existente no se ve afectada, pero si se necesita establecer una nueva conexión después de que el token haya expirado, la autenticación fallará. El adaptador de PostgreSQL evita esto refrescando el token dinámicamente cada vez que el pool abre una nueva conexión, pero el adaptador de MySQL no tiene un mecanismo equivalente.
Para tareas de larga duración como trabajos por lotes o migraciones de datos, llama a getPrisma() al inicio de cada unidad de trabajo en lugar de una vez para toda la operación. Debido a que getPrisma() siempre crea un cliente nuevo y obtiene un nuevo token IAM para MySQL, esto asegura que cada conexión se autentique con un token válido.