Saltar al contenido
DedicatedPHP Contactar

Monolito modular vs microservicios en PHP: cómo decidir

Criterios técnicos y operativos para decidir entre reforzar un monolito PHP o extraer servicios sin trasladar complejidad innecesaria.

Diagrama editorial de decisión entre un monolito PHP modular y servicios independientes conectados por contratos

La decisión entre monolito modular vs microservicios en PHP no se resuelve por el número de módulos, la antigüedad del código ni la popularidad de una arquitectura. Una aplicación empresarial puede crecer de forma saludable dentro de un único despliegue si mantiene límites claros. A la inversa, dividirla prematuramente puede convertir llamadas internas sencillas en una red de contratos, colas, reintentos y problemas de coordinación.

La pregunta útil no es «¿debemos usar microservicios?», sino «¿qué capacidad de negocio necesita evolucionar, fallar, desplegar o escalar de forma independiente, y podemos asumir el coste de operarla así?». La respuesta debe partir del dominio y de la operación real, no de un diagrama objetivo.

El crecimiento funcional no exige servicios separados

El crecimiento funcional no exige servicios separados — guía visual de DedicatedPHP

Añadir integraciones, procesos asíncronos o áreas de producto no implica que cada una deba tener su propio servicio. Un monolito puede contener módulos bien delimitados, trabajos en segundo plano, colas y adaptadores para sistemas externos sin perder coherencia operativa.

La primera intervención suele ser reducir el acoplamiento interno. Si un módulo de facturación importa directamente clases de pedidos, modifica sus tablas o conoce reglas internas de inventario, el problema no se arregla automáticamente al mover código a otro repositorio. Solo se transforma en acoplamiento de red y de datos.

Un monolito modular busca que cada capacidad tenga una interfaz interna explícita, dependencias dirigidas y reglas propias. En PHP, esto puede materializarse en espacios de nombres por dominio, contratos de aplicación, controladores delgados, casos de uso definidos y adaptadores para persistencia o APIs externas. El hecho de desplegar todo junto sigue siendo compatible con estas fronteras.

Qué analizar antes de cambiar la arquitectura

Antes de discutir tecnología, identifique las capacidades de negocio: por ejemplo, gestión de pedidos, catálogo, identidad, facturación, procesamiento documental o notificaciones. Una capacidad no equivale necesariamente a una entidad ni a una pantalla; agrupa reglas y decisiones que deberían cambiar por razones similares.

  • Propietario: determine quién mantiene las reglas, prioriza cambios y responde ante incidencias.
  • Datos: identifique qué información crea y gobierna cada capacidad, quién puede modificarla y qué lecturas cruzadas necesita.
  • Flujos críticos: dibuje el recorrido de una operación relevante, incluyendo validaciones, dependencias externas y pasos asíncronos.
  • Ritmo de cambio: diferencie modificaciones frecuentes de cambios puntuales. La frecuencia aislada no basta; importa si obliga a coordinar equipos o releases.
  • Perfil de carga: separe el tráfico interactivo de tareas intensivas de CPU, memoria, almacenamiento o llamadas a terceros.
  • Impacto de fallo: establezca qué sucede si una capacidad se degrada durante minutos u horas y si el núcleo del negocio puede seguir operando.

Este inventario revela dependencias que a menudo permanecen ocultas: transacciones compartidas, consultas directas a tablas ajenas, reglas duplicadas en controladores y tareas programadas que actualizan varios dominios. Extraer sin resolverlas produce servicios formalmente separados pero funcionalmente entrelazados.

Seis señales para conservar un monolito modular

Estas señales favorecen reforzar el diseño interno antes que distribuir responsabilidades:

  1. Los cambios suelen atravesar varios módulos. Si una funcionalidad de negocio requiere modificar pedidos, precios y facturación de manera coordinada, separar puede multiplicar los despliegues y los contratos.
  2. La consistencia inmediata es central. Cuando una operación necesita una única transacción de base de datos para preservar invariantes críticos, un límite distribuido añade decisiones complejas de compensación.
  3. El equipo es pequeño o comparte propiedad. Varios servicios exigen disciplina de operación, guardias, pipelines, versiones y diagnóstico por cada unidad.
  4. La carga se escala de forma similar. Si los componentes crecen al mismo ritmo y no existe un cuello de botella aislable, la separación no aporta una ventaja clara.
  5. Los límites de dominio aún son inestables. Extraer una capacidad mientras sus reglas, vocabulario y responsabilidades cambian constantemente fija una frontera prematura.
  6. La observabilidad y automatización son limitadas. Sin logs estructurados, métricas, trazas, alertas y despliegues repetibles, cada salto de red hará más costoso investigar una incidencia.

Conservar el monolito no significa aceptar código global. El objetivo es que el módulo pueda evolucionar con autonomía lógica aunque comparta proceso, repositorio y release con otros.

Seis señales que justifican un servicio independiente

La extracción es más defendible cuando se combinan varias de estas condiciones, no cuando aparece una sola:

  1. Existe una responsabilidad acotada y entendible. El servicio tiene una misión concreta, reglas cohesionadas y un lenguaje de dominio propio.
  2. Puede ser propietario de sus datos. Gestiona su almacenamiento y expone operaciones, eventos o consultas acordadas, en lugar de permitir acceso directo a sus tablas.
  3. Necesita despliegues independientes de verdad. Su ciclo de cambio debe avanzar sin coordinar cada release con el núcleo.
  4. Su carga es diferenciada. Un proceso de conversión, búsqueda, generación de archivos o cálculo intensivo puede requerir escalado y recursos distintos.
  5. Su fallo puede aislarse. El sistema puede degradarse de forma explícita si esa capacidad no responde, mediante reintentos, estados pendientes o trabajo diferido.
  6. Hay propiedad operativa suficiente. Un equipo o responsable puede mantener su ciclo de vida, alertas, incidentes, seguridad y compatibilidad.

Una API no convierte por sí sola un módulo en microservicio. La independencia depende también de datos, despliegue, operación y capacidad de tomar decisiones sin depender de internals de otra aplicación.

Costes que aparecen al separar responsabilidades

Una llamada de función falla de manera distinta a una llamada HTTP, un mensaje en cola o una consulta remota. Tras la extracción aparecen latencia, timeouts, autenticación entre servicios, límites de tasa, indisponibilidad parcial y versiones incompatibles.

También cambia el modelo de consistencia. Si un servicio confirma una operación y otro no recibe o no procesa el evento, hay que decidir cómo detectar el estado, reintentar sin duplicar efectos y compensar cuando sea necesario. Los consumidores de eventos deben ser idempotentes; por ejemplo, procesar dos veces un mensaje no debe emitir dos documentos ni cobrar dos veces.

La operación gana complejidad: correlación de peticiones, trazas distribuidas, paneles de métricas, retención de logs, gestión de secretos, políticas de backup y pruebas de recuperación. Además, cada contrato necesita reglas de compatibilidad. Añadir campos opcionales suele ser menos disruptivo que cambiar semántica, eliminar campos o reutilizar un estado con un significado nuevo.

Arquitectura de transición dentro de PHP

La ruta de menor riesgo es modularizar antes de extraer. Defina una capa de aplicación para cada capacidad, con casos de uso que reciban comandos o consultas y devuelvan resultados bien definidos. Oculte el acceso a base de datos detrás de repositorios o puertos cuando ello represente una dependencia relevante; no convierta cada clase en una abstracción sin propósito.

El resto del monolito debe utilizar el módulo mediante su interfaz pública interna, no mediante sus entidades o tablas. Si se necesitan notificaciones asíncronas, publique eventos de dominio o integración desde un punto controlado. Un patrón de salida transaccional puede ayudar a registrar el cambio de negocio y el evento pendiente en la misma transacción, para que un proceso posterior lo entregue de forma fiable.

Esta fase permite comprobar si el límite es real. Si la interfaz interna crece sin parar, exige objetos privados de otros módulos o necesita transacciones compartidas en cada caso de uso, todavía no es un candidato sólido para separación.

Cómo definir el primer límite de servicio

El primer servicio debe tener una responsabilidad fácil de explicar y una dependencia limitada del núcleo. Documente cuatro elementos antes de escribir infraestructura:

  • Responsabilidad: qué decisiones toma y cuáles quedan explícitamente fuera.
  • API o eventos: entradas, salidas, errores, autenticación, límites de tiempo e idempotencia.
  • Propiedad de datos: qué almacena, qué identificadores externos conserva y qué información consulta mediante contratos.
  • Compatibilidad: cómo coexistirán productores y consumidores durante cambios de versión, incluidos los mensajes retrasados.

Evite diseñar una API como espejo de las tablas. Un contrato debe expresar operaciones o hechos de negocio, no exponer detalles de persistencia que bloquearán cambios posteriores.

Ejemplo: procesamiento documental sin fragmentar el backoffice

Considere un backoffice PHP que gestiona expedientes y debe generar, validar y almacenar documentos. Al principio, el procesamiento puede vivir como un módulo interno: recibe una solicitud de generación, registra el trabajo, ejecuta una tarea asíncrona y actualiza un estado visible para el usuario.

La extracción se vuelve razonable si la generación consume recursos muy distintos, necesita dependencias de conversión específicas, recibe picos propios y puede funcionar con una solicitud documental que contenga los datos mínimos necesarios. El servicio documental no debería consultar libremente las tablas del expediente. El backoffice puede enviar una orden con un identificador, plantilla aplicable, versión de datos y destino; el resultado vuelve como evento o estado consultable.

Antes de ello, conviene aclarar que una plantilla define la estructura de salida, mientras que un modelo puede referirse a datos de dominio o a un sistema de IA. Si se incorporase IA para clasificar documentos, harían falta un caso de uso delimitado, evaluación con datos representativos, revisión humana ante decisiones sensibles, protección de datos, control de coste y una alternativa manual o basada en reglas cuando el proveedor falle.

Comprobaciones antes de extraer

Comprobaciones antes de extraer — guía visual de DedicatedPHP

No trate la extracción como un despliegue técnico aislado. Defina una activación gradual para un subconjunto controlado de operaciones, distinta de anunciar el cambio a todos los usuarios. Mantenga un plan de convivencia y reversión mientras se valida el comportamiento.

  • Pruebas de contrato entre productor y consumidor, además de pruebas unitarias e integración.
  • Métricas de latencia, errores, reintentos, colas pendientes, duplicados y tiempo hasta completar el proceso.
  • Identificadores de correlación para seguir una operación entre el monolito, colas y servicio.
  • Procedimientos de recuperación: reejecución segura, reconciliación de estados, backup y restauración.
  • Reglas explícitas para degradación funcional cuando el servicio no esté disponible.
  • Un criterio de salida: qué evidencia demostrará que la extracción redujo un problema concreto y no solo desplazó complejidad.

La mejor decisión arquitectónica es la que protege la evolución del producto sin imponer una plataforma desproporcionada. Un monolito PHP modular, medible y bien delimitado suele ser el paso correcto hasta que una capacidad demuestre una necesidad verificable de independencia.

¿Quieres aplicar estas ideas a tu proyecto?Hablemos de tu plataforma PHP.
Ver servicio relacionado