Carlos Cifuentes
Microfrontends · Comunicación

Cómo se comunican los microfrontends y qué evitar

Los microfrontends bien cortados tienen poco que decirse. Para lo que queda, hay unos pocos mecanismos simples, ordenados aquí del acoplamiento más débil al más fuerte.

Por Carlos Cifuentes · Arquitecto frontend · Actualizado 2026-10-02

Empieza por comunicar menos

La cantidad de comunicación entre dos microfrontends mide qué tan bueno es el límite entre ellos. Si dos áreas intercambian mensajes todo el tiempo, probablemente son una sola área, y unirlas es más barato que construir un protocolo.

La mayoría de las necesidades legítimas cae en tres grupos: abrir una pantalla de otra área, conocer algo global como el usuario actual, y enterarse de que algo pasó en otra parte.

1. La URL

La navegación con parámetros es el mecanismo por defecto. Pedidos envía al usuario a /customers/42?tab=payments, y el área de clientes carga lo que necesita.

La URL sobrevive a una recarga, se puede compartir y probar, y no crea ninguna dependencia de código entre equipos. Las reglas están en Rutas entre microfrontends.

2. El backend como fuente de verdad

Cuando dos áreas muestran los mismos datos de negocio, cada una los pide a la API. No se comparte nada en el navegador. Esto cuesta alguna petición duplicada de vez en cuando, que el caché HTTP puede reducir. A cambio, ningún área depende de que otra esté cargada.

3. Servicios compartidos de la plataforma

Pocas cosas son realmente globales: el usuario actual, el idioma, los permisos, los feature flags. Vienen de un paquete pequeño de plataforma que el host inicializa.

En Angular con federation, es un servicio en una librería que se comparte como singleton. Mantén su API acotada y casi solo de lectura: observables o signals para leer, pocos métodos para escribir. Un servicio compartido al que le crece un método por cada funcionalidad se convirtió en estado global con otro nombre.

4. Custom events

Para avisar que algo pasó, el navegador ya tiene un mecanismo. Funciona entre frameworks, entre versiones de un framework y con web components.

// publica: orders
window.dispatchEvent(new CustomEvent('orders:order-paid', {
  detail: { orderId: '981' }
}));

// se suscribe: notifications
window.addEventListener('orders:order-paid', (e) => {
  refreshBadge(e.detail.orderId);
});

5. Un event bus pequeño

Un event bus es un envoltorio delgado y tipado sobre la misma idea, publicado como paquete compartido: publish(name, payload) y subscribe(name, handler), que devuelve una función para cancelar la suscripción.

Agrega tres cosas sobre los eventos crudos: chequeo de tipos de los payloads, un catálogo único de todos los eventos y un lugar donde registrar el tráfico durante el desarrollo. En Angular, un servicio singleton con un Subject de RxJS cumple, pero solo para los remotos que comparten la misma instancia de la librería. Los eventos del DOM y BroadcastChannel llegan también a las partes que no la comparten.

Reglas para diseñar eventos

  • Nombra los eventos como hechos, con el dueño como prefijo. orders:order-paid dice qué pasó. Una orden como cart:refresh-now le dice al código de otro equipo qué hacer, y eso acopla a los dos.
  • Envía identificadores y valores pequeños.
  • Trata los eventos como una API pública. Documéntalos. Agregar campos es seguro. Renombrarlos o eliminarlos requiere un periodo de deprecación.
  • Supón que puede no haber nadie escuchando. El remoto suscriptor puede no estar cargado. El que publica no debe depender de una reacción.
  • Supón que el evento se pudo perder. Un remoto que se carga después debe poder obtener el estado actual desde la API.
  • Cancela la suscripción al destruir. Los listeners en window viven más que los componentes y producen fugas de memoria.
  • No esperes respuesta. Si necesitas una respuesta, necesitas una llamada a función. Usa un servicio compartido o la API.

Qué evitar

Estado global mutable compartido. Un único store que todos los microfrontends leen y escriben, u objetos en window usados de la misma manera, trae de vuelta el acoplamiento del monolito sin sus herramientas. Cualquier equipo puede romper a cualquier otro. El orden de las publicaciones empieza a importar. Nadie puede cambiar la forma del estado, porque nadie sabe quién depende de ella.

Otros patrones que traen problemas:

  • Importar directamente el código de otro remoto. Es una dependencia en tiempo de build entre dos equipos que debían ser independientes.
  • Usar localStorage como canal de mensajes dentro de una página. Es síncrono, no tiene tipos y sigue ahí después de cuando debió limpiarse.
  • Poner tokens o datos personales en eventos. Cualquier script de la página puede escuchar. El manejo de sesión se cubre en Autenticación compartida.

Qué mecanismo para qué necesidad

NecesidadMecanismo
Abrir una pantalla de otra áreaURL
Los mismos datos de negocio en dos áreasCada una los pide a la API
Usuario actual, idioma, permisosServicio compartido de plataforma
Avisar que algo pasóCustom event o event bus
Hablar con una parte en otro framework o versiónCustom events; atributos y propiedades de un custom element
Hablar con contenido en un iframepostMessage, con verificación de origen en ambos lados

Checklist

  1. ¿Hay un catálogo escrito de eventos entre áreas, con un dueño para cada uno?
  2. ¿Cada remoto sigue funcionando cuando se carga solo, sin ningún otro remoto presente?
  3. ¿Hay dos áreas que intercambien más que un puñado de tipos de evento? Revisa el límite, y mira Equipos, dueños y la ley de Conway.

Más en esta sección

¿Planeas una migración o una plataforma de microfrontends?

En una llamada de 20 minutos me cuentas tu situación y te digo cómo la abordaría. Si todavía no vale la pena, también te lo digo.

Escríbeme por LinkedIn