Volver a notas técnicas
10 min

Nota técnica

Microfrontends + BFF en banca regulada

Cómo desacoplar 3 equipos frontend en un proyecto MEP de 4 meses, con BFF en Node.js orquestando 12+ servicios Oracle — sin fragmentar la UX.

En números

4 meses

A go-live

3

Microfrontends

12+

Servicios Oracle

100%

TypeScript

El contexto

En proyectos bancarios de alta criticidad, varios equipos frontend necesitan avanzar en paralelo sobre un backend legacy (Oracle, servicios SOAP/REST heterogéneos). El desafío no es solo técnico: hay compliance, plazos fijos y cero tolerancia a regresiones en flujos de dinero. En Santander MEP hipotecario teníamos 4 meses y 3 squads con dominios distintos: onboarding, simulación y confirmación.

Por qué microfrontends (y cuándo no)

La arquitectura microfrontend permite que cada squad posea su dominio de UI con deploy independiente. El costo es coordinación: design system compartido, contratos entre shells y versionado de dependencias comunes. La regla que aplicamos: microfrontend solo donde el acoplamiento de equipos lo justificaba — no fragmentar por capas técnicas ("MFE de botones"). Tres MFEs, tres equipos, tres flujos de negocio.

Contratos tipados BFF ↔ React

El error más caro fue intentar compartir tipos ad-hoc. Definimos contratos en TypeScript compartidos entre BFF y cada MFE. El BFF expone endpoints con shape estable; los MFEs nunca conocen Oracle directamente.

TypeScript
// packages/shared-types/src/mep-simulation.ts
export interface SimulationRequest {
  mortgageId: string;
  amount: number;
  currency: "USD" | "ARS";
}

export interface SimulationResponse {
  rate: number;
  totalCost: number;
  breakdown: { label: string; value: number }[];
  expiresAt: string; // ISO — el BFF normaliza timezone
}

// El MFE solo consume SimulationResponse.
// El BFF traduce SOAP/Oracle → este shape.

El rol del BFF

La capa Backend-for-Frontend en Node.js actúa como traductor: agrega llamadas a múltiples servicios Oracle, normaliza errores, adapta payloads al shape que React necesita y oculta la complejidad del backend al cliente. Un solo punto de entrada tipado reduce bugs de integración ~40% vs. adapters por equipo.

TypeScript · BFF handler
// bff/src/routes/simulation.ts
export async function getSimulation(req: Request, res: Response) {
  try {
    const [rate, limits, customer] = await Promise.all([
      oracleClient.getRate(req.body.mortgageId),
      oracleClient.getLimits(req.body.mortgageId),
      oracleClient.getCustomer(req.user.id),
    ]);

    const response: SimulationResponse = mapOracleToSimulation({
      rate, limits, customer, amount: req.body.amount,
    });

    return res.json(response);
  } catch (error) {
    // Error normalizado — el MFE nunca ve stack Oracle
    return res.status(mapOracleError(error)).json({
      code: "SIMULATION_FAILED",
      message: getUserFacingMessage(error),
    });
  }
}

Shell host mínimo

El shell host no es un monolito disfrazado: solo routing entre MFEs, autenticación compartida y layout base. Cada MFE se monta lazy. Si el shell crece demasiado, volvés al acoplamiento que querías evitar.

React · shell
// shell/src/App.tsx
const OnboardingMFE = lazy(() => import("mfe_onboarding/App"));
const SimulationMFE = lazy(() => import("mfe_simulation/App"));
const ConfirmationMFE = lazy(() => import("mfe_confirmation/App"));

export function App() {
  return (
    <AuthProvider>
      <ShellLayout>
        <Routes>
          <Route path="/onboarding/*" element={<OnboardingMFE />} />
          <Route path="/simulation/*" element={<SimulationMFE />} />
          <Route path="/confirm/*" element={<ConfirmationMFE />} />
        </Routes>
      </ShellLayout>
    </AuthProvider>
  );
}

Lecciones aplicadas

Entregamos en 4 meses priorizando: (1) contratos tipados antes de escribir UI, (2) design system mínimo acordado en semana 2, (3) code review cruzado entre squads, (4) entrega incremental por flujo de negocio. La clave fue no sobre-ingenierizar: BFF delgado, MFEs acotados, Oracle invisible para React.

Takeaways

  • BFF como orquestador delgado — no un segundo backend monolítico
  • Contratos TypeScript compartidos antes de paralelizar equipos
  • 3 MFEs = 3 flujos de negocio, no 3 capas técnicas
  • Errores Oracle normalizados en BFF — UX consistente en todos los MFEs
  • Go-live en 4 meses con 3 squads en paralelo sin acoplar releases
MicrofrontendsBFFNode.jsTypeScriptBanking