¿Qué es la Arquitectura Hexagonal?
La Arquitectura Hexagonal, también conocida como Ports & Adapters, es un estilo arquitectónico propuesto por Alistair Cockburn cuyo objetivo principal consiste en aislar completamente la lógica de negocio de cualquier detalle técnico.
En una aplicación tradicional es habitual encontrar reglas de negocio mezcladas con controladores REST, consultas SQL, anotaciones de frameworks o librerías externas. Con el paso del tiempo esto provoca un fuerte acoplamiento que dificulta el mantenimiento y hace que cualquier cambio tenga un impacto mayor del esperado.
La Arquitectura Hexagonal propone invertir esa dependencia. El dominio deja de conocer tecnologías como Spring Boot, Hibernate, Kafka o PostgreSQL y pasa a depender únicamente de abstracciones. De esta manera el negocio permanece estable mientras la infraestructura puede evolucionar libremente.

¿Qué aprenderás en esta guía?
- Qué problemas resuelve realmente la Arquitectura Hexagonal.
- Diferencias respecto a la arquitectura tradicional por capas.
- Cómo funcionan los Puertos y Adaptadores.
- Cómo organizar un proyecto profesional con Spring Boot.
- Cómo integrar DDD dentro de la arquitectura.
- Errores habituales que cometen la mayoría de desarrolladores.
- Cuándo utilizarla y cuándo no merece la pena.
"El dominio nunca debe depender de la infraestructura. La infraestructura debe depender siempre del dominio."
¿Qué problema resuelve la Arquitectura Hexagonal?
Antes de entender la solución, es necesario comprender el problema. La mayoría de aplicaciones Java comienzan con una arquitectura sencilla basada en capas: controladores, servicios, repositorios y base de datos.
Este enfoque funciona correctamente en proyectos pequeños, pero conforme la aplicación crece empiezan a aparecer dependencias entre capas, reglas de negocio repartidas por todo el código y una fuerte dependencia del framework utilizado.

Los síntomas aparecen muy rápido
Acoplamiento elevado
Las reglas de negocio terminan dependiendo de Spring, Hibernate, anotaciones JPA o incluso consultas SQL.
Pruebas complicadas
Para probar una simple regla de negocio es necesario levantar Spring Boot, una base de datos o numerosos mocks.
Cambios costosos
Una modificación pequeña obliga a tocar controladores, servicios, repositorios y configuración.
Dependencia tecnológica
Cambiar JPA por MongoDB, Kafka por RabbitMQ o REST por GraphQL implica modificar gran parte de la aplicación.
En muchas empresas la lógica de negocio acaba dependiendo más del framework que del propio dominio del negocio.
El verdadero problema
El problema no es Spring Boot, Hibernate o cualquier otra tecnología. El problema aparece cuando el dominio conoce esos detalles técnicos.
Si nuestras entidades contienen anotaciones de persistencia, nuestros casos de uso llaman directamente a repositorios JPA y la lógica de negocio conoce cómo se almacenan los datos, el dominio deja de ser independiente y cualquier cambio tecnológico afecta directamente al corazón de la aplicación.

⚠ El error más habitual
Muchos desarrolladores creen que utilizar paquetes llamadosdomain, application oinfrastructure ya significa utilizar Arquitectura Hexagonal.
No es cierto.
Lo importante no es la estructura de carpetas sino la dirección de las dependencias. El dominio nunca debe depender de Spring, Hibernate, Kafka, RabbitMQ o cualquier otra tecnología externa.
¿Cómo funciona la Arquitectura Hexagonal?
La Arquitectura Hexagonal organiza toda la aplicación alrededor del dominio de negocio. En lugar de colocar la base de datos o el framework en el centro del diseño, el protagonista pasa a ser el propio negocio.
Todo aquello relacionado con tecnologías externas (REST, Kafka, PostgreSQL, MongoDB, Redis, RabbitMQ, servicios cloud, etc.) permanece fuera del núcleo de la aplicación y únicamente se comunica con él a través de contratos bien definidos llamados Puertos (Ports).

El dominio siempre ocupa el centro
El dominio contiene únicamente las reglas del negocio. No conoce Spring Boot. No conoce Hibernate. No conoce PostgreSQL. No conoce Kafka. Tampoco sabe si la aplicación es una API REST, GraphQL o una aplicación de escritorio.
Regla número uno
El dominio nunca depende de la infraestructura.
Los Puertos (Ports)
Los puertos son interfaces que definen cómo el dominio necesita comunicarse con el exterior.
El dominio no sabe cómo se almacenan los datos. Simplemente define un contrato indicando qué necesita.
public interface CustomerRepository {
Customer save(Customer customer);
Optional<Customer> findById(Long id);
}Obsérvese que esta interfaz no depende de Spring Data JPA, Hibernate ni ninguna otra librería.
Los Adaptadores (Adapters)
Los adaptadores implementan esos contratos utilizando una tecnología concreta.
@Repository
public class JpaCustomerRepository
implements CustomerRepository {
private final SpringCustomerRepository repository;
@Override
public Customer save(Customer customer){
return repository.save(customer);
}
}Si mañana decides sustituir PostgreSQL por MongoDB, únicamente cambiará este adaptador. El dominio continuará exactamente igual.
❌ Arquitectura tradicional
- El dominio depende de JPA.
- Las entidades contienen anotaciones.
- La lógica conoce la base de datos.
- Difícil de probar.
✅ Arquitectura Hexagonal
- El dominio no conoce tecnologías.
- Todo depende del dominio.
- Los adaptadores son intercambiables.
- Muy sencilla de testear.
La Arquitectura Hexagonal no intenta organizar carpetas. Intenta organizar las dependencias.
Implementando Puertos y Adaptadores
Una vez comprendido el concepto de Arquitectura Hexagonal, llega el momento de trasladarlo a un proyecto real.
Uno de los errores más habituales consiste en pensar que basta con crear carpetas llamadas domain o application. En realidad, lo importante es respetar la dirección de las dependencias y mantener el dominio completamente aislado de cualquier tecnología externa.

Estructura recomendada
src/main/java
com.freelance.architecture
├── domain
│ ├── model
│ ├── ports
│ ├── services
│ └── exceptions
│
├── application
│ └── usecases
│
├── infrastructure
│ ├── persistence
│ ├── messaging
│ ├── configuration
│ └── security
│
└── adapters
├── inbound
│ └── rest
└── outbound
├── jpa
└── kafka
Esta organización permite localizar rápidamente cada responsabilidad y evita que las tecnologías de infraestructura se mezclen con el dominio.
El caso de uso
Los Use Cases representan las acciones que el negocio puede realizar. No contienen detalles de infraestructura ni conocen cómo se almacenan los datos.
public class CreateCustomerUseCase {
private final CustomerRepository repository;
public CreateCustomerUseCase(CustomerRepository repository){
this.repository = repository;
}
public Customer execute(CreateCustomerCommand command){
Customer customer = new Customer(
command.name(),
command.email()
);
return repository.save(customer);
}
}💡 Observa un detalle importante
El caso de uso únicamente conoce la interfazCustomerRepository. Nunca sabe si la información se almacenará en PostgreSQL, MongoDB o cualquier otro sistema.
El adaptador de persistencia
El adaptador es el responsable de traducir el contrato definido por el dominio hacia una tecnología concreta.
@Repository
public class JpaCustomerRepositoryAdapter
implements CustomerRepository {
private final SpringDataRepository repository;
@Override
public Customer save(Customer customer){
CustomerEntity entity = mapper.toEntity(customer);
return mapper.toDomain(
repository.save(entity)
);
}
}Si el día de mañana decides sustituir JPA por MongoDB únicamente tendrás que crear un nuevo adaptador.
El controlador REST
El controlador deja de contener reglas de negocio y se limita a recibir la petición HTTP, construir el comando correspondiente y delegar en el caso de uso.
@RestController
@RequestMapping("/customers")
public class CustomerController {
private final CreateCustomerUseCase useCase;
@PostMapping
public CustomerResponse create(
@RequestBody CreateCustomerRequest request){
return mapper.toResponse(
useCase.execute(
mapper.toCommand(request)
)
);
}
}
Cada componente conoce únicamente la responsabilidad que le corresponde. Esa separación es la clave para construir aplicaciones fáciles de evolucionar.
Implementación completa con Spring Boot
Uno de los mayores errores al adoptar Arquitectura Hexagonal consiste en pensar que Spring Boot desaparece de la aplicación. No es así.
Spring Boot sigue siendo una excelente herramienta para construir APIs, configurar la aplicación e integrar componentes externos. La diferencia es que deja de ocupar el centro del diseño y pasa a convertirse en un simple detalle de infraestructura.
En una aplicación correctamente diseñada, el dominio podría ejecutarse incluso sin Spring Boot. El framework únicamente conecta el mundo exterior con los casos de uso.
Dependencias Maven
La infraestructura depende de Spring Boot, mientras que el dominio no tiene ninguna dependencia del framework.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>Configuración de Spring
Los casos de uso son clases Java normales. Spring únicamente se encarga de instanciarlas mediante configuración.
@Configuration
public class CustomerConfiguration {
@Bean
CreateCustomerUseCase createCustomerUseCase(
CustomerRepository repository){
return new CreateCustomerUseCase(repository);
}
}Ventajas de este enfoque
Dominio independiente
Ninguna clase del dominio necesita anotaciones de Spring.
Testing sencillo
Los casos de uso pueden probarse con JUnit sin levantar el contexto de Spring Boot.
Infraestructura sustituible
Cambiar PostgreSQL por MongoDB únicamente implica crear un nuevo adaptador.
Mayor mantenibilidad
Las reglas de negocio permanecen estables aunque cambien las tecnologías.
Una petición completa
Cuando un cliente realiza una petición HTTP, el flujo siempre es el mismo:
HTTP Request
↓
REST Controller
↓
Application Use Case
↓
Output Port
↓
Persistence Adapter
↓
Database
↓
Application Use Case
↓
REST ResponseSpring Boot ya no es el corazón de la aplicación. Es simplemente una herramienta para conectar el dominio con el exterior.
Arquitectura Hexagonal y Domain-Driven Design
Uno de los mayores beneficios de la Arquitectura Hexagonal es que encaja de forma natural con Domain-Driven Design (DDD). Ambos enfoques persiguen exactamente el mismo objetivo: situar el dominio de negocio en el centro de la aplicación y evitar que las decisiones técnicas condicionen las reglas del negocio.
Mientras que la Arquitectura Hexagonal define cómo deben organizarse las dependencias, Domain-Driven Design proporciona un conjunto de patrones para modelar correctamente el dominio.
Las piezas del dominio
Entities
Objetos con identidad propia que evolucionan durante el ciclo de vida de la aplicación.
Value Objects
Objetos inmutables definidos únicamente por sus atributos y no por una identidad.
Aggregates
Agrupan varias entidades garantizando la consistencia del dominio.
Repositories
Interfaces del dominio que permiten recuperar y almacenar agregados sin conocer la infraestructura.
Una entidad de dominio
public class Customer {
private CustomerId id;
private Name name;
private Email email;
public Customer(Name name, Email email){
this.name = name;
this.email = email;
}
public void changeEmail(Email newEmail){
this.email = newEmail;
}
}Observa que esta entidad no contiene anotaciones de Hibernate, Lombok ni Spring Boot. Es una clase Java pura cuyo único propósito consiste en representar reglas de negocio.
💡 Regla importante
Las entidades nunca deberían depender de tecnologías externas. El dominio debe poder ejecutarse incluso sin Spring Boot.
Value Objects
public record Email(String value){
public Email{
if(value == null || !value.contains("@")){
throw new IllegalArgumentException();
}
}
}Al encapsular la validación dentro del propio Value Object evitamos repetir reglas por toda la aplicación y conseguimos un dominio mucho más consistente.
¿Dónde viven los casos de uso?
Los casos de uso pertenecen a la capa de aplicación. Son los encargados de coordinar el dominio utilizando los puertos definidos por éste.
CreateCustomerUseCase
↓
CustomerRepository
↓
Customer Aggregate
↓
CustomerCreatedEventEventos de dominio
En aplicaciones empresariales es muy habitual utilizar Domain Events para comunicar cambios importantes del negocio sin acoplar distintos módulos entre sí.
public record CustomerCreatedEvent(
UUID customerId,
Instant createdAt
){}Más adelante estos eventos podrán publicarse mediante Kafka, RabbitMQ o cualquier otro mecanismo sin modificar el dominio.
Domain-Driven Design no sustituye a la Arquitectura Hexagonal. Ambos patrones se complementan para construir aplicaciones más mantenibles y preparadas para evolucionar.
Beneficios reales de la Arquitectura Hexagonal
La Arquitectura Hexagonal no es una moda ni una forma diferente de organizar carpetas. Su objetivo es reducir el impacto que tienen los cambios tecnológicos sobre el negocio y facilitar la evolución del software durante años.
En aplicaciones empresariales que permanecen activas durante mucho tiempo, el coste de mantenimiento suele superar ampliamente el coste del desarrollo inicial. Una buena arquitectura permite que ese crecimiento sea sostenible.

Mayor mantenibilidad
Separar claramente el dominio de la infraestructura permite localizar rápidamente cualquier cambio. Las reglas de negocio permanecen en un único lugar y no aparecen repartidas entre controladores, repositorios, filtros o configuraciones.
✔ Código más limpio
Cada componente tiene una única responsabilidad.
Testing mucho más sencillo
Los casos de uso pueden ejecutarse sin levantar Spring Boot ni conectar una base de datos.
CreateCustomerUseCase useCase =
new CreateCustomerUseCase(fakeRepository);
Customer customer =
useCase.execute(command);
assertEquals("Javier", customer.getName());Esto reduce considerablemente el tiempo de ejecución de las pruebas y permite detectar errores mucho antes.
Independencia tecnológica
Cambiar una tecnología deja de ser una operación traumática. El dominio permanece estable mientras los adaptadores evolucionan.
Persistencia
PostgreSQL → MongoDB
Mensajería
RabbitMQ → Kafka
API
REST → GraphQL
Framework
Spring Boot → Quarkus
Preparada para Microservicios
La Arquitectura Hexagonal facilita enormemente la migración desde un monolito hacia microservicios. Los casos de uso ya se encuentran desacoplados de la infraestructura, por lo que resulta mucho más sencillo extraer funcionalidades hacia servicios independientes.
Escalabilidad del equipo
En proyectos grandes participan varios equipos de desarrollo de forma simultánea. Una arquitectura bien definida reduce conflictos, facilita las revisiones de código y acelera la incorporación de nuevos desarrolladores.
| Arquitectura tradicional | Arquitectura Hexagonal |
|---|---|
| Alto acoplamiento | Bajo acoplamiento |
| Difícil de probar | Muy testeable |
| Dependencia del framework | Dominio independiente |
| Cambios costosos | Evolución sencilla |
| Mayor deuda técnica | Menor deuda técnica |
💡 Mi recomendación
La Arquitectura Hexagonal aporta un enorme valor en aplicaciones empresariales con una vida útil larga, múltiples integraciones y equipos de desarrollo numerosos.
Para un pequeño CRUD con pocas pantallas probablemente suponga una sobreingeniería innecesaria.
Errores más comunes al implementar Arquitectura Hexagonal
Después de participar en proyectos de modernización de aplicaciones Java, uno de los patrones que más se repite es que muchas implementaciones dicen utilizar Arquitectura Hexagonal, pero en realidad únicamente han cambiado la organización de las carpetas.
La verdadera Arquitectura Hexagonal no consiste en mover clases entre paquetes, sino en controlar cuidadosamente la dirección de las dependencias.
❌ Error 1 — El dominio depende de Spring
Es habitual encontrar entidades anotadas con@Entity,@Component o incluso@Service.
El dominio debe ser completamente independiente del framework.
❌ Error 2 — Inyectar JpaRepository directamente
Muchos casos de uso reciben directamente un JpaRepository.
// Incorrecto
@Service
public class CreateCustomerUseCase {
private final JpaCustomerRepository repository;
}El caso de uso únicamente debería conocer un Puerto.
// Correcto
public class CreateCustomerUseCase {
private final CustomerRepository repository;
}❌ Error 3 — Pensar que la arquitectura son las carpetas
Cambiar el nombre de los paquetes adomain,application oinfrastructureno convierte automáticamente una aplicación en Hexagonal.
Lo importante es quién depende de quién.
❌ Error 4 — Crear un puerto para absolutamente todo
Algunos equipos generan decenas de interfaces innecesarias.
Los puertos únicamente deben existir cuando realmente representan una dependencia del dominio hacia el exterior.
❌ Error 5 — Abusar de los DTO
Es frecuente encontrar cinco o seis objetos diferentes para mover exactamente la misma información entre capas.
Utiliza DTO únicamente cuando exista un límite claro entre el dominio y el exterior.
❌ Error 6 — Convertir todo en un microservicio
Arquitectura Hexagonal no significa Microservicios.
Un monolito bien diseñado suele ser mucho mejor que decenas de microservicios mal diseñados.
❌ Error 7 — Sobreingeniería
No todas las aplicaciones necesitan esta arquitectura.
Para un pequeño CRUD interno probablemente sea suficiente una arquitectura tradicional.
¿Cuándo utilizar Arquitectura Hexagonal?
| ✔ Recomendada | ❌ No recomendable |
|---|---|
| Aplicaciones empresariales | CRUD sencillos |
| Microservicios | Proyectos temporales |
| Integraciones complejas | POCs |
| Equipos grandes | Aplicaciones de una sola pantalla |
| Software de larga duración | Proyectos académicos |
La mejor arquitectura no es la más compleja. Es la más sencilla capaz de resolver el problema.
Conclusiones
La Arquitectura Hexagonal no pretende sustituir Spring Boot, Hibernate, JPA o cualquier otra tecnología. Su objetivo consiste en proteger el conocimiento más importante de una organización: las reglas de negocio.
A lo largo de esta guía hemos visto cómo separar el dominio de la infraestructura mediante Puertos y Adaptadores, consiguiendo aplicaciones más fáciles de mantener, probar y evolucionar.
Este cambio de perspectiva permite que tecnologías como bases de datos, brokers de mensajería o frameworks puedan cambiar con el paso del tiempo sin obligar a reescribir la lógica de negocio.

Checklist antes de adoptar Arquitectura Hexagonal
¿Cuándo utilizar Arquitectura Hexagonal?
✔ Muy recomendable
- Aplicaciones empresariales.
- Microservicios.
- Sistemas críticos.
- Equipos numerosos.
- Software con muchos años de vida.
- Integraciones complejas.
✖ Probablemente no sea necesaria
- CRUD sencillos.
- Aplicaciones temporales.
- Pruebas de concepto.
- Proyectos académicos pequeños.
Próximos pasos
La Arquitectura Hexagonal suele combinarse con otros patrones que permiten construir plataformas empresariales robustas y preparadas para evolucionar.
Domain-Driven Design
Modelado del dominio mediante Entities, Value Objects, Aggregates y Repositories.
Event Driven Architecture
Comunicación desacoplada mediante eventos utilizando Kafka o RabbitMQ.
Microservicios
Separación de capacidades de negocio independientes y despliegues autónomos.
Cloud Native
Contenedores, Kubernetes, observabilidad y escalabilidad sobre plataformas cloud.
Continúa aprendiendo
Si este artículo te ha resultado útil, los siguientes temas que te recomiendo son:
- Spring AI + RAG
- Virtual Threads en Java 21
- Observabilidad con OpenTelemetry
- Arquitecturas Event Driven con Kafka
- Domain-Driven Design
¿Te gustaría aplicar esta arquitectura en tu empresa?
Diseño arquitecturas Java modernas, escalables y cloud-native para proyectos empresariales.
