Desarrollo de Servicios – NestJS Backend¶
Pautas específicas para microservicios construidos con NestJS.
Stack recomendado¶
- Runtime: Node.js 20+
- Framework: NestJS 10+
- Lenguaje: TypeScript
- ORM: TypeORM (preferido)
- Base de datos: PostgreSQL
- Documentación: Swagger/OpenAPI
Estructura de proyecto¶
backend/
├── src/
│ ├── config/ # Configuración centralizada
│ ├── modules/ # Módulos de dominio (users, products, etc.)
│ ├── common/ # Código compartido (decorators, guards, filters...)
│ ├── database/ # Migraciones y seeds
│ ├── app.module.ts
│ ├── app.controller.ts
│ ├── app.service.ts
│ └── main.ts
├── test/
├── Dockerfile
├── Makefile
├── package.json
├── env.example
└── README.md
Configuración centralizada (ConfigService)¶
Archivo src/config/configuration.ts:
export const configuration = () => ({
nodeEnv: process.env.NODE_ENV || 'development',
database: {
type: 'postgres' as const,
host: process.env.DATABASE_HOST || 'postgres',
port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
username: process.env.DATABASE_USER || 'postgres',
password: process.env.DATABASE_PASSWORD || 'postgres',
database: process.env.DATABASE_NAME || 'app_db',
synchronize: process.env.NODE_ENV !== 'production',
logging: process.env.NODE_ENV === 'development',
},
auth: {
jwtSecret: process.env.JWT_SECRET || 'change_me_in_production',
},
logging: {
level: process.env.LOG_LEVEL || 'info',
},
});
Uso en AppModule:
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [configuration],
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
...config.get('database'),
entities: ['dist/**/*.entity{.ts,.js}'],
migrations: ['dist/database/migrations/*{.ts,.js}'],
}),
}),
// otros módulos de dominio
],
})
export class AppModule {}
Bootstrap y Swagger¶
En main.ts:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
transformOptions: { enableImplicitConversion: true },
}),
);
const config = new DocumentBuilder()
.setTitle('API Backend')
.setDescription('API del ecosistema')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api/docs', app, document);
app.enableCors({
origin: process.env.CORS_ORIGIN || '*',
});
await app.listen(3000);
}
bootstrap();
Health check y logging¶
- Exponer
/healthcomo endpoint simple. - Usar
Loggerde NestJS o un wrapper para logs estructurados.
@Controller('health')
export class HealthController {
@Get()
health() {
return { ok: true };
}
}
Migraciones y base de datos¶
- Mantener migraciones en
src/database/migrations. - Ejecutar migraciones desde scripts de npm o Makefile.
- Nunca usar
synchronizeen producción.
Buenas prácticas¶
- Separar módulos por dominio (no monolitos de un solo módulo gigante).
- Usar DTOs en controllers para todo input externo.
- Encapsular lógica de negocio en servicios, no en controllers.
- Manejar excepciones con filtros globales o interceptores.