Distributed monolith
Many services, one tangled dependency graph, no real autonomy.
Microservices anti-patterns often start from good intentions: faster delivery, team autonomy, or cleaner scaling. The trouble appears when service boundaries are shallow, the data model is still shared, or every business flow requires synchronous hops across half the platform. Then the system becomes a distributed monolith with worse debugging.
If ordering, payments, inventory, and customer profiles all call each other synchronously for routine flows and still share database ownership, the platform has the cost of microservices without the benefit of independent change. Recognizing these failure signatures early is one of the highest-value microservices skills.
The most common anti-pattern is premature distribution. Others include services defined by technical layers, shared databases masquerading as autonomy, tiny services that only forward requests, and central platform components that become hidden monoliths. Healthy microservices are not small for their own sake. They are cohesive, independently evolvable, and explicit about consistency boundaries.
Anti-pattern awareness is especially important because teams can keep adding containers and pipelines while the real architectural problem remains unchanged.
Many services, one tangled dependency graph, no real autonomy.
Simple business requests require too many synchronous service hops.
Multiple services still co-own the same database truths.
| Anti-pattern | What it looks like | Healthier direction |
|---|---|---|
| Distributed monolith | Every deployment needs cross-team coordination | Strengthen boundaries or consolidate |
| Shared database | Services query each other's tables directly | Move to database-per-service and published contracts |
| Nanoservices | Tiny services add network hops without ownership gains | Merge around cohesive capabilities |
| Chatty orchestration | Request path fans across many dependencies | Use asynchronous collaboration or better capability design |
package org.javaomnibus.checkout;
public final class CheckoutFacade {
public Receipt place(CheckoutRequest request) {
customerService.verify(request.customerId());
pricingService.price(request.lines());
inventoryService.check(request.lines());
orderService.create(request);
paymentService.authorize(request.payment());
loyaltyService.apply(request.customerId());
notificationService.sendConfirmation(request.customerId());
return receiptService.fetchLatest(request.customerId());
}
}