Microsserviços com Java 21 e Spring Boot 3: Clean Architecture, DDD e Event-Driven Architecture
Como estruturar microsserviços em Java 21 e Spring Boot 3 com Clean Architecture, DDD e eventos — limites, contratos e operação.
Microsserviços em Java 21 e Spring Boot 3 só sustentam escala se os limites de domínio forem reais. Clean Architecture e DDD organizam o interior; eventos coordenam o exterior sem acoplar ciclos de vida.
Comece pelos limites de contexto
Antes de criar repositórios, desenhe bounded contexts e linguagem ubíqua. Um serviço por tabela é fragmentação, não arquitetura. Um serviço por capacidade de negócio com dono claro é o alvo.
Clean Architecture no módulo
adapters/web ──► application ──► domain adapters/db ──► application ──► domain adapters/mq ──► application ──► domain
public final class OpenAccountService implements OpenAccountUseCase {
private final AccountRepository accounts;
private final DomainEventPublisher events;
public OpenAccountService(AccountRepository accounts, DomainEventPublisher events) {
this.accounts = accounts;
this.events = events;
}
@Override
public AccountId handle(OpenAccountCommand cmd) {
Account account = Account.open(cmd.customerId(), cmd.product());
accounts.save(account);
events.publish(account.pullEvents());
return account.id();
}
}O que Java 21 muda na prática
- Virtual threads para I/O-bound sob Tomcat/Netty com cuidado em pooling de JDBC
- Records e pattern matching para contratos internos mais claros
- Sequenced collections e APIs modernas sem reinventar utilitários
Spring Boot 3 e observabilidade
Boot 3 assume Jakarta EE e encaixa bem com Micrometer Observation e tracing OpenTelemetry. Padronize correlation id na borda e propague em mensagens.
Event-Driven Architecture
Use eventos de domínio para fatos que já ocorreram. Evite orquestração síncrona em cadeia entre muitos serviços. Outbox pattern evita dual-write entre banco e broker.
@Transactional
public void saveAndOutbox(Account account, DomainEvent event) {
accountRepository.save(account);
outboxRepository.insert(OutboxMessage.from(event));
}Testes e limites
- Testes de domínio sem Spring
- Contratos consumer-driven nas APIs
- Não distribua transações XA como primeira opção
- Evite shared database entre contextos