Saltar al contenido principal

Arquitectura Backend — API Modular por Dominio

El backend de Finnova es una API REST monolítica modular construida en Node.js + Express (TypeScript), desplegada en contenedores Docker sobre AWS. Es un monolito en cuanto a despliegue (un solo proceso/servicio), pero modular por dominio internamente: cada módulo de negocio es independiente y aislado, lo que permite extraerlo a un servicio separado más adelante si el dominio lo justifica.

Para la vista de infraestructura y despliegue completa, ver el Manual de arquitectura.


Stack del backend

CapaTecnologíaRol
RuntimeNode.jsEntorno de ejecución
Framework HTTPExpress.jsRouting y middleware
LenguajeTypeScript (strict: true)Tipado estático
Base de datosPostgreSQLAlmacén relacional principal (+ réplica de lectura)
Object storageAWS S3Contenido de cursos (video/material)
Reverse proxyNginxTLS termination interno y proxy a la app
ContenedoresDockerEmpaquetado y despliegue
InfraestructuraAWS EC2 + Load BalancerCómputo y balanceo HTTPS
PagosStripeProcesamiento de suscripciones (PCI-DSS delegado)

Vista de despliegue (infraestructura)

Elementos clave

  • Load Balancer (HTTPS): único punto de entrada; termina TLS y enruta al servidor de aplicación.
  • API Gateway: punto de entrada interno de la API; valida el JWT y delega a los módulos de dominio (ver Control de Sesiones).
  • PostgreSQL primario + réplica de lectura: el primario absorbe escrituras; la réplica es read-only y respalda lecturas pesadas y backups automatizados.
  • AWS S3: almacena el contenido de cursos (video/material); la base relacional solo guarda metadatos.
  • Stripe: procesa suscripciones y notifica cambios vía webhooks (ver Stripe — Suscripciones).

Módulos de dominio

La API se divide en módulos de negocio independientes, orquestados por el API Gateway:

MóduloResponsabilidadRequisitos asociados (ejemplos)
AuthRegistro, login (correo/Google/Apple), JWT, gestión de cuentaRF01–RF11
Finance Data Collection (FDC)Conexión de cuentas bancarias, ingresos/gastos, patrimonio y deuda, dashboardRF12–RF23
InvestmentsRecomendaciones IA, inversiones populares, broker/FinnovaRF24–RF31
SubscriptionModelos de suscripción, métodos de pago, facturación, renovacionesRF32–RF46
CoursesCatálogo de cursos, reproducción, progreso, certificadosRF47–RF62
AccountingDeclaración anual, análisis de facturasRF63–RF66
Rewards / LeaderboardGeneración y canje de recompensas, rankingRF67–RF69

El módulo Subscription es el único que se comunica con un servicio externo (Stripe). El módulo Courses es el único que lee de S3 además de PostgreSQL.


Estructura interna de un módulo

Cada módulo dentro de src/modules/ aplica una arquitectura en capas (controller → service → repository), separando transporte HTTP, lógica de negocio y acceso a datos:

src/
├── modules/
│ └── <domain>/
│ ├── <domain>.controller.ts # Maneja requests/responses HTTP
│ ├── <domain>.service.ts # Lógica de negocio
│ ├── <domain>.repository.ts # Acceso a base de datos
│ ├── <domain>.routes.ts # Definición de rutas
│ ├── <domain>.dto.ts # Data Transfer Objects (validación de entrada)
│ └── <domain>.types.ts # Tipos e interfaces del dominio
├── shared/ # Middleware, errores, utilidades transversales
├── config/ # Configuración (env, db, etc.)
└── app.ts # Bootstrap de Express

Responsabilidad de cada capa

ArchivoResponsabilidadNo debe
*.routes.tsMapear rutas HTTP a métodos del controller, montar middlewareContener lógica
*.controller.tsLeer request, validar con DTO, llamar al service, formar responseTener lógica de negocio o SQL
*.dto.tsDefinir y validar la forma de la entradaAcceder a datos
*.service.tsImplementar reglas de negocio del dominioConocer detalles de HTTP o SQL crudo
*.repository.tsAcceso a la base de datos (queries)Contener reglas de negocio
*.types.tsTipos e interfaces del dominio

Regla: el flujo de una petición siempre va routes → controller → service → repository. El controller nunca llama directo al repository, y el service nunca arma respuestas HTTP. Esto mantiene cada capa testeable de forma aislada.


Flujo de una petición autenticada


Persistencia y datos

  • PostgreSQL primario: todas las escrituras y la mayoría de lecturas transaccionales.
  • Réplica de lectura (read-only): descarga lecturas pesadas (dashboards, reportes) y sirve de base para backups.
  • Backups automatizados: programados desde la réplica para no impactar el primario.
  • AWS S3: contenido binario de cursos; PostgreSQL guarda únicamente metadatos y referencias.

El cifrado en tránsito y en reposo, y la gestión de secretos, se detallan en Cifrado y Almacenamiento Sensible.


Seguridad e integraciones


Convenciones aplicadas

  • Nomenclatura de archivos: camelCase (userService.ts); clases/tipos en PascalCase, interfaces con prefijo I. Ver Convenciones de Código.
  • Código en inglés, comentarios en español.
  • TypeScript strict, prohibido any salvo excepción documentada.
  • CI bloqueante: lint + tests + security audit en verde para mergear.

Recursos relacionados