Llevar una aplicación NestJS con TypeORM a producción implica resolver un problema frecuente: ¿cómo ejecutar migraciones en un entorno donde las variables de ambiente y las dependencias funcionan de forma diferente? Aquí se aborda paso a paso la configuración necesaria para que el CLI de TypeORM se conecte correctamente a la base de datos en Heroku, desde la creación del archivo de configuración hasta la ejecución exitosa de migraciones y la validación de endpoints protegidos.
¿Por qué TypeORM necesita una configuración especial para producción?
TypeORM mantiene tres conexiones posibles en un proyecto típico: la del módulo de la aplicación, una conexión nativa con el driver oficial y la que utiliza el CLI para ejecutar migraciones. En desarrollo, la configuración suele darse mediante variables de ambiente individuales como host, puerto y contraseña. Sin embargo, en producción la conexión llega en una sola variable llamada DATABASE_URL [01:01].
El problema es que no se puede simplemente asignar una variable de ambiente a otra dentro del archivo .env. Por eso, TypeORM ofrece la posibilidad de usar un archivo JavaScript llamado ormconfig.js, donde se puede acceder de forma programática a process.env.DATABASE_URL y pasarla como la URL de conexión [02:27].
¿Cómo se estructura el archivo ormconfig.js?
El archivo exporta un objeto con la configuración de conexión. Lo esencial es indicar el tipo de base de datos (en este caso postgres), y asignar la URL directamente desde la variable de entorno [03:07]:
javascript
module.exports = {
type: 'postgres',
url: process.env.DATABASE_URL,
synchronize: false,
logging: false,
entities: ['src/**/.entity.ts'],
migrations: ['src/database/migrations/.ts'],
cli: {
migrationsDir: 'src/database/migrations',
},
};
- synchronize debe estar en
false para evitar cambios automáticos en el esquema.
- logging puede activarse con una variable de ambiente si se necesita depurar.
- Las rutas de entities y migrations se definen en formato de array.
- La propiedad
cli.migrationsDir indica dónde se generan las migraciones.
Una vez creado este archivo, las variables individuales de conexión en el .env deben comentarse para evitar conflictos [04:55].
¿Qué errores comunes aparecen al correr migraciones en Heroku?
El primer intento de ejecutar heroku run npm run migrations:run suele fallar porque ts-node no se encuentra en el entorno productivo [06:25]. Esto ocurre porque ts-node está listado como dependencia de desarrollo. Heroku instala las devDependencies solo durante el build y luego las elimina.
La solución es mover tanto ts-node como typescript a las dependencias de producción, ya que las migraciones están escritas en TypeScript y necesitan ser interpretadas [07:15].
¿Cómo conviven dos configuraciones de TypeORM?
Para desarrollo se mantiene la configuración original que usa ts-node directamente. Para producción se crea una configuración paralela que ejecuta con Node [08:00]:
{
"typeorm:prod": "node --require ts-node/register ./node_modules/typeorm/cli.js",
"migrations:prod": "npm run typeorm:prod -- migration:run"
}
- El comando
migrations:prod utiliza la configuración typeorm:prod.
- El comando de drop no se habilita en producción por seguridad.
- Es explícito en su nombre para evitar confusiones con los comandos de desarrollo.
El segundo error frecuente es la falta de configuración SSL [09:48]. Heroku requiere una propiedad ssl en la conexión. Al agregarla en ormconfig.js con ssl: { rejectUnauthorized: false }, la conexión se establece correctamente.
¿Cómo validar que todo funciona en el entorno productivo?
Una vez ejecutadas las migraciones con éxito [10:55], se pueden probar los endpoints directamente. En este caso se crearon marcas, categorías y usuarios utilizando endpoints sin protección, y luego se validó la autenticación con JWT [12:10]:
- Un administrador puede crear productos tras autenticarse y obtener un token.
- Un cliente recibe un error de rol al intentar crear productos.
- Un token alterado devuelve error de autorización.
- El endpoint público de obtener productos funciona sin token [14:02].
Heroku proporciona una instancia de Postgres con plan gratuito para desarrollo. Para datos productivos reales, es recomendable evaluar planes con backups y mayor estabilidad [14:35].
Una mejora importante es automatizar la ejecución de migraciones con integración continua. Cada vez que se hace push a master, un pipeline puede verificar si hay migraciones pendientes y ejecutarlas automáticamente, ya que TypeORM mantiene una tabla interna que registra qué migraciones se han corrido [15:05]. Heroku ofrece herramientas para configurar este flujo, aunque también es válido mantener el control manual si se prefiere mayor supervisión sobre cada release.