When your system grows from a single application into a collection of independent services, keeping track of how everything connects gets messy fast. A PlantUML class diagram for microservices architecture gives you a clear, text-based way to map out each service, its responsibilities, and how services depend on each other. Unlike hand-drawn diagrams that go stale, PlantUML code lives in your repository and updates alongside your codebase. If you're trying to communicate your microservices structure to a team, onboard new developers, or plan a refactor, this approach saves real time and reduces confusion.
What Does a PlantUML Class Diagram for Microservices Actually Show?
A class diagram in PlantUML represents your microservices as classes or components, their internal structure (like key methods or endpoints), and the relationships between them. Think of each microservice as a box. Inside that box, you list the service name, its main operations or REST endpoints, and maybe its data models. Lines between the boxes show how services talk to each other through REST calls, message queues, or shared data stores.
This is different from a deployment diagram or a sequence diagram. A class diagram focuses on the static structure: what exists and how things relate. If you need to see how requests flow at runtime, a sequence diagram with PlantUML might be more useful. But for understanding the overall architecture at a glance, class diagrams work well.
How Do You Write PlantUML Class Diagram Code for Microservices?
Here's a practical example. Say you have an e-commerce system with three services: an Order Service, a Payment Service, and an Inventory Service. Here's how you might represent that in PlantUML:
@startuml
skinparam classAttributeIconSize 0
package "Order Service" {
class OrderController {
+createOrder(order: OrderRequest): Order
+getOrder(orderId: String): Order
+cancelOrder(orderId: String): void
}
class Order {
-orderId: String
-customerId: String
-items: List<OrderItem>
-status: OrderStatus
-totalAmount: BigDecimal
}
class OrderService {
+processOrder(order: Order): Order
+updateStatus(orderId: String, status: OrderStatus): void
}
OrderController --> OrderService
OrderService --> Order
}
package "Payment Service" {
class PaymentController {
+processPayment(payment: PaymentRequest): Payment
+refundPayment(paymentId: String): Refund
}
class Payment {
-paymentId: String
-orderId: String
-amount: BigDecimal
-status: PaymentStatus
}
class PaymentService {
+charge(orderId: String, amount: BigDecimal): Payment
+refund(paymentId: String): Refund
}
PaymentController --> PaymentService
PaymentService --> Payment
}
package "Inventory Service" {
class InventoryController {
+checkStock(productId: String): StockLevel
+reserveStock(orderId: String, items: List<Item>): Reservation
}
class StockLevel {
-productId: String
-quantity: int
-warehouseId: String
}
class InventoryService {
+reserve(orderId: String, items: List<Item>): boolean
+release(orderId: String): void
}
InventoryController --> InventoryService
InventoryService --> StockLevel
}
OrderService ..> PaymentService : <
This code produces a diagram with three clear packages, each containing its classes and relationships. The dashed arrows between packages show the service-to-service communication. You can render this in any PlantUML editor, your CI pipeline, or directly in a README file.
What Are the Key Elements to Include in a Microservices Class Diagram?
A useful microservices class diagram usually covers these things:
- Service boundaries Use
packageblocks to group classes by service. This mirrors how your teams and repos are organized. - API controllers or entry points Show the public interface each service exposes. These are the methods other services or clients actually call.
- Domain models List the core data structures each service owns. Keep it to the most important fields, not every column in your database.
- Service dependencies Draw arrows showing which services depend on which. Label them with the communication style (REST, gRPC, async message, etc.).
- Shared concepts If two services reference the same entity (like a Customer ID), you can show that relationship without duplicating the full model.
You don't need to show every class in every service. Focus on the parts that help someone understand the system's structure. If you need to show how data flows through specific operations, pairing this with an activity diagram using PlantUML gives a more complete picture.
How Do You Handle Service Communication in the Diagram?
Microservices communicate in different ways, and your diagram should reflect that. Here's how to show common patterns:
Synchronous calls (REST or gRPC): Use a dashed arrow with a stereotype label.
OrderService ..> PaymentService : <<REST API>>
Asynchronous messaging (Kafka, RabbitMQ): Use a dashed arrow with a different stereotype.
OrderService ..> NotificationService : <<Kafka Event>>
Shared database (not recommended, but it exists): Show it as a dependency on a shared class or component.
OrderService ..> SharedDatabase : <<jdbc>>
Being specific about communication style matters because it affects latency, failure handling, and coupling things that directly impact how your system behaves under load.
What Common Mistakes Should You Avoid?
Here are mistakes that make PlantUML microservices diagrams less useful:
- Showing too much detail. If every private field, getter, and setter is in the diagram, nobody will read it. Show the public API and key domain fields only.
- Ignoring service boundaries. Dumping all classes into one flat diagram defeats the purpose. Use packages to represent service ownership.
- Forgetting to update the diagram. A stale diagram is worse than no diagram. Keeping your PlantUML code in version control near the service code helps with this.
- Mixing levels of abstraction. Don't put infrastructure details (load balancers, DNS entries) on the same diagram as domain models. Use separate views.
- No legend or labels. If your arrows mean different things, label them. Assume the reader has never seen your system before.
How Do You Keep PlantUML Microservices Diagrams Maintainable?
The biggest advantage of text-based diagrams is that they live in your codebase. Here are a few ways to make that work well in practice:
- One diagram per bounded context or domain. Don't try to fit your entire system into one diagram. Split it into logical pieces.
- Use
!includedirectives. PlantUML lets you split definitions across files. You can keep shared model definitions in one file and include them where needed. - Generate diagrams in CI. Add a step to your build pipeline that renders PlantUML to SVG or PNG and publishes it alongside your docs.
- Use skinparam for consistency. Set font sizes, arrow styles, and colors once in a shared config file so all diagrams look the same.
- Version your diagrams alongside the code. When a service API changes, the diagram update should be part of the same pull request.
If you also need to document the behavior of individual services, combining class diagrams with state machine diagrams in PlantUML helps capture how a service handles different states and transitions.
Can You Auto-Generate PlantUML from Your Codebase?
Yes, and this is where the approach gets practical at scale. Several tools can scan your Java, C#, or Python code and produce PlantUML class diagrams automatically:
- PlantUML itself has a reverse-engineering feature for Java bytecode using
plantuml.jarwith the-tpngor-tsvgflags. - IntelliJ IDEA has a PlantUML integration plugin that can generate diagrams from selected classes.
- Swagger/OpenAPI to PlantUML converters can generate service interface diagrams from your API specs.
Auto-generation works well as a starting point, but you'll almost always want to clean up the output. Generated diagrams tend to include too much. Trim them to show only what matters for understanding the architecture.
What Should You Do Next?
Here's a quick checklist to get started with PlantUML class diagrams for your microservices:
- List your services and their primary responsibilities.
- For each service, identify 3–5 key classes or endpoints to include.
- Map out which services call which, and how (REST, events, gRPC).
- Write the PlantUML code using
packageblocks for service boundaries. - Render the diagram and share it with your team for feedback.
- Store the
.pumlfiles in your repo and set up CI rendering. - Review and update the diagrams during sprint reviews or architecture discussions.
Start with one bounded context. Get feedback. Expand from there. A good diagram doesn't need to cover everything it needs to answer the question someone on your team is actually asking right now.
Plantuml Sequence Diagram Examples with Complete Code Tutorials
How to Draw an Activity Diagram Using Plantuml Syntax,
Plantuml State Machine Diagram Cheatsheet Reference
Plantuml Devops Pipeline Component Diagram Code Tutorial
Best Diagram Code Editors for Software Architects in 2025
How to Create a Mermaid Diagram in Markdown Using Mermaid Syntax