Antes de subir tu API de NestJS a producción, necesitas blindarla con seguridad básica, habilitar CORS, fijar la versión de Node y compilar el proyecto a JavaScript. Esa lista corta marca la diferencia entre una app frágil y una lista para recibir tráfico real desde web, móvil o escritorio.
¿Cómo proteger tu API con Helmet en NestJS?
La primera capa de seguridad la pones con Helmet, un paquete Node que actúa como un casco frente a las vulnerabilidades más conocidas en APIs.
La instalación y configuración son mínimas, pero el impacto en seguridad es alto. Solo necesitas tres pasos:
- Instalar el paquete con
npm i helmet.
- Importarlo dentro del archivo
main.ts.
- Aplicarlo con
app.use(helmet()) antes de levantar el servidor.
Con eso ya cubres los ataques conocidos por defecto. Si quieres ajustar reglas adicionales, Helmet expone opciones avanzadas, pero la configuración base es la que la documentación oficial de NestJS recomienda como mínimo viable [03:50].
¿Qué hace Helmet en una API? Aplica cabeceras HTTP de seguridad para protegerte contra vulnerabilidades comunes como inyecciones, clickjacking o filtrado de información sensible.
¿Qué son los CORS y cuándo debes habilitarlos?
Los CORS (Cross Origin Resource Sharing) son el permiso que tu API da para recibir requests desde dominios distintos al suyo. Por defecto, NestJS los deshabilita por seguridad.
Si tu backend va a servir a una aplicación web, móvil y de escritorio al mismo tiempo, necesitas habilitarlos. Una app móvil en Android o iOS no tiene un origin fijo, así que sin CORS abiertos esos requests serían rechazados.
La habilitación se hace con app.enableCors() dentro de main.ts, y puedes pasarle un objeto con tres llaves clave:
origin: define qué dominios pueden consumir tu API.
methods: lista los verbos HTTP permitidos (GET, POST, PUT, DELETE).
allowedHeaders: especifica qué cabeceras se aceptan en la petición.
Si tu producto es solo web, lo correcto es restringir origin al dominio real, por ejemplo myblog.ai. Si tienes clientes móviles o de escritorio, lo común es aceptar cualquier origen. Tu lógica de negocio decide qué tan estricta es esa regla.
typescript
app.enableCors({
origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
allowedHeaders: 'Content-Type, Accept',
});
¿Cómo configurar la versión de Node y compilar para producción?
Proveedores como Heroku o Railway leen el package.json y respetan el campo engines para saber qué versión de Node ejecutar. Sin esa señal, podrías terminar con una versión incompatible corriendo tu app.
La recomendación para este proyecto es Node 20 o superior. En Node 18, por ejemplo, el módulo de hashing aún no está disponible de forma global; desde la 20 sí lo está, así que evitas errores silenciosos en autenticación.
"engines": {
"node": ">=20"
}
¿Qué hace npm run build en un proyecto NestJS?
Como trabajas con TypeScript en desarrollo, necesitas transpilarlo a JavaScript puro antes de producción. Eso lo hace npm run build, que genera la carpeta dist con un archivo main.js listo para ejecutarse en un runtime de Node.
Dentro de dist vas a encontrar todos tus DTOs, entities y modelos convertidos a JavaScript. Esa es la versión real que correrá en el servidor.
El comando start:prod apunta a dist/main, así que si lo ejecutas sin haber hecho el build primero, vas a recibir un error porque la carpeta no existe.
¿Por qué correr build antes de start:prod? Porque start:prod ejecuta JavaScript ya compilado desde la carpeta dist. Sin build, esa carpeta no existe y Node no encuentra el archivo de entrada.
¿Cuál es el orden correcto para lanzar a producción?
El flujo recomendado tiene tres pasos en este orden exacto:
npm run build para transpilar todo el código TypeScript a JavaScript.
- Ejecutar las migraciones pendientes contra la base de datos.
npm run start:prod para arrancar el servidor en modo productivo.
Las migraciones van en medio porque ya estás en un ambiente real y necesitas que el esquema de la base de datos esté sincronizado antes de aceptar tráfico. Si no hay migraciones pendientes, el comando lo confirma y sigues al siguiente paso [10:30].
¿Qué cambia al correr la app en modo producción?
Cuando levantas el servidor con start:prod, ya no hay capa de TypeScript ni recarga en caliente. Node ejecuta JavaScript puro directamente desde dist.
Eso trae dos ganancias inmediatas:
- Mayor velocidad de respuesta porque desaparece la capa de transpilación en tiempo real.
- Optimizaciones del build que reducen el tamaño y mejoran el arranque.
Las pruebas con endpoints como GET /users o GET /posts siguen funcionando igual, pero notarás que responden más rápido que en modo start:dev. Esa diferencia es la que tus usuarios finales van a percibir.
¿Ya tienes tu checklist listo para tu próximo deploy? Cuéntame en los comentarios cuál de estos pasos sueles olvidar y cómo lo resolviste.