NestJS es un framework progresivo de Node.js para construir aplicaciones backend escalables y mantenibles. Combina patrones de programación orientada a objetos, funcional y reactiva funcional, apoyándose en TypeScript moderno, ESM y decoradores para ofrecer una experiencia de desarrollo cercana a la de frameworks frontend como Angular.
Construido con TypeScript como lenguaje principal, NestJS se apoya en las versiones LTS de Node.js y aprovecha las últimas características del lenguaje: tipos estrictos, ESM nativo, satisfies, tipos condicionales y using para gestión de recursos. El resultado es un stack coherente y tipado de extremo a extremo que encaja tanto en APIs REST y GraphQL como en microservicios y proyectos enterprise.
flowchart LR
Cliente[Cliente HTTP/WS] --> Guards[Guards]
Guards --> Interceptors[Interceptors]
Interceptors --> Pipes[Pipes - Validación]
Pipes --> Controller[Controller]
Controller --> Service[Service]
Service --> Repo[Repositorio TypeORM / Prisma]
Repo --> DB[(PostgreSQL / MySQL)]
Controller --> Filters[Exception Filters]
Filosofía y arquitectura del framework
NestJS adopta una arquitectura modular que facilita la organización del código en aplicaciones complejas. El framework utiliza decoradores de TypeScript y un sistema de inyección de dependencias robusto, permitiendo crear aplicaciones altamente testeables y mantenibles.
La estructura basada en módulos permite dividir la aplicación en componentes reutilizables y bien definidos. Cada módulo encapsula un conjunto relacionado de funcionalidades, promoviendo la separación de responsabilidades y facilitando el desarrollo en equipo.
@Module({
imports: [DatabaseModule],
controllers: [UserController],
providers: [UserService],
exports: [UserService]
})
export class UserModule {}
Sistema de controladores y enrutamiento
Los controladores en NestJS manejan las peticiones HTTP entrantes y devuelven respuestas al cliente. Utilizan decoradores para definir rutas y métodos HTTP, proporcionando una sintaxis clara y expresiva para la definición de endpoints.
@Controller('users')
export class UserController {
@Get()
findAll(): string {
return 'Esta acción devuelve todos los usuarios';
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return 'Esta acción añade un nuevo usuario';
}
}
El enrutamiento se gestiona mediante decoradores que mapean métodos HTTP específicos a funciones del controlador. Esta aproximación permite crear APIs RESTful de manera intuitiva y mantiene el código organizado según las operaciones que realiza.
Inyección de dependencias y servicios
El sistema de inyección de dependencias es uno de los pilares fundamentales de NestJS. Los servicios se definen como providers que pueden ser inyectados en controladores u otros servicios, promoviendo la reutilización de código y facilitando las pruebas unitarias.
@Injectable()
export class UserService {
private readonly users: User[] = [];
create(user: User): User {
this.users.push(user);
return user;
}
findAll(): User[] {
return this.users;
}
}
Los providers pueden tener diferentes scopes de vida, desde singleton hasta request-scoped, permitiendo un control granular sobre la gestión de instancias y el estado de la aplicación.
Integración con bases de datos
NestJS se integra perfectamente con TypeORM y Prisma, los dos ORM más usados hoy en el ecosistema TypeScript. Esta integración permite trabajar con bases de datos relacionales (PostgreSQL, MySQL, MariaDB, SQL Server) y bases de datos no relacionales mediante una capa tipada. TypeORM aporta el patrón Active Record o Data Mapper con decoradores, mientras que Prisma genera un cliente tipado a partir de un esquema schema.prisma. En cualquiera de los dos casos se sigue respetando la separación servicio/repositorio.
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
}
El patrón Repository facilita la separación entre la lógica de negocio y el acceso a datos, permitiendo crear consultas complejas de manera type-safe y manteniendo la consistencia en toda la aplicación.
Validación y transformación de datos
El framework incluye un sistema de pipes que permite validar y transformar datos de entrada antes de que lleguen a los controladores. Utilizando bibliotecas como class-validator, es posible definir reglas de validación declarativas directamente en los DTOs (Data Transfer Objects).
export class CreateUserDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
@IsInt()
@Min(18)
age: number;
}
La serialización automática permite controlar qué datos se exponen en las respuestas de la API, proporcionando una capa adicional de seguridad y control sobre la información que se envía al cliente.
Middleware y interceptores
Los middlewares en NestJS funcionan de manera similar a Express.js, permitiendo ejecutar código antes de que la petición llegue al controlador. Son útiles para tareas como logging, autenticación, y modificación de peticiones.
Los interceptores proporcionan una funcionalidad más avanzada, permitiendo transformar tanto peticiones como respuestas, implementar caché, manejar timeouts, y ejecutar lógica adicional antes y después de la ejecución del método del controlador.
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`Después... ${Date.now() - now}ms`))
);
}
}
Seguridad y autenticación
NestJS proporciona herramientas robustas para implementar autenticación y autorización. El framework se integra con Passport.js, permitiendo utilizar múltiples estrategias de autenticación como JWT, OAuth, y autenticación local.
Los guards actúan como middleware de autorización, determinando si una petición debe ser procesada por el controlador basándose en criterios como roles de usuario, permisos, o estado de autenticación.
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Controller('protected')
@UseGuards(JwtAuthGuard)
export class ProtectedController {
@Get()
getProtectedResource() {
return 'Este recurso está protegido';
}
}
Gestión de errores y logging
El manejo de errores en NestJS es centralizado y configurable. El framework proporciona filtros de excepción que capturan errores no manejados y los transforman en respuestas HTTP apropiadas.
El sistema de logging integrado permite registrar eventos importantes de la aplicación, con diferentes niveles de severidad y la posibilidad de configurar múltiples transportes para los logs.
Herramientas de desarrollo
El NestJS CLI es una herramienta de línea de comandos que acelera el desarrollo proporcionando generadores para controladores, servicios, módulos, y otros componentes. También incluye comandos para ejecutar, construir, y probar la aplicación.
nest generate controller users
nest generate service users
nest generate module users
La integración con TypeScript proporciona tipado estático, autocompletado inteligente, y detección temprana de errores, mejorando significativamente la experiencia de desarrollo y la calidad del código. Las últimas versiones de NestJS aprovechan ESM, tsconfig moderno y bundlers como SWC para acelerar la compilación y el arranque en frío. Jest y @nestjs/testing cubren los tests unitarios e integración, y hay soporte oficial para Pact, supertest y Testcontainers cuando se necesitan pruebas end-to-end con dependencias reales.
Escalabilidad y rendimiento
NestJS está diseñado para aplicaciones empresariales que requieren alta escalabilidad y rendimiento. El framework soporta microservicios, permitiendo dividir aplicaciones monolíticas en servicios más pequeños y especializados.
La arquitectura basada en módulos facilita el desarrollo en equipo y permite que diferentes partes de la aplicación evolucionen independientemente, reduciendo el acoplamiento y mejorando la mantenibilidad a largo plazo.
El soporte nativo para programación asíncrona y la integración con RxJS permiten manejar operaciones concurrentes de manera eficiente, optimizando el rendimiento de la aplicación en escenarios de alta carga.