Enhancing Observability in Spring Boot Microservices with Micrometer, OpenTelemetry, and Spring Modulith Starter Insight

In the previous post, we explored the structure of a Spring Boot application using advanced modular architecture. This time, let’s shift gears to discuss how to enhance observability in Spring Boot microservices and applications. Specifically, we’ll delve into how integrating Micrometer, OpenTelemetry, and the Spring Modulith Starter Insight can offer comprehensive performance insights across your application’s various layers.


Before diving into the implementation, make sure you have the following set up:

  1. Java 21: Ensure Java 21 is installed using SDKMAN.
  2. Docker & Docker Compose: Required for setting up the local environment.
  3. Repository Clone: Clone the examples repository to your local environment.
git clone https://github.com/dmakariev/examples.git
cd examples/spring-boot/bookstore

Basic Observability in Spring Boot

A Spring Boot microservice by default exposes limited performance data at the RestController level. While useful, this data is often insufficient for a comprehensive understanding of the interactions between controllers, services, repositories, event publishers, and listeners. basic!

Integrating Advanced Observability Tools

To gain deeper insights, you can enhance observability by integrating the following dependencies:

Spring Modulith Starter Insight


Micrometer Tracing Bridge OpenTelemetry


OpenTelemetry Exporter Zipkin


Application Configuration

Update your application.properties file to enable tracing:


After integrating Micrometer, OpenTelemetry, and the Spring Modulith Starter Insight, the screenshot below shows the detailed performance data captured, including interactions between controllers, services, and other components. This enhanced trace, visualized using Zipkin, highlights the robust observability capabilities now at our disposal. enhanced!

Running the Application

Start the application with Zipkin enabled

docker compose up --build

Alternatively, you can run only the backend in a separate window

docker compose up --build backend

Cyclic Dependency Example


We’ve implemented a new CyclicDependencyController in the com.makariev.examples.spring.bookstore.product package. This controller introduces a cyclic dependency between the product and inventory packages, deliberately triggering modular structure verification errors.

public class CyclicDependencyController {

    private final InventoryService inventoryService;

    public CyclicDependencyController(InventoryService inventoryService) {
        this.inventoryService = inventoryService;

    public ResponseEntity<List<Inventory>> getAllInventories() {
        final List<Inventory> inventories = inventoryService.findAll();
        return ResponseEntity.ok(inventories);

Modularity Tests

Enable the ModularityTests class to verify the modular structure

public class ModularityTests {

    private final ApplicationModules modules = ApplicationModules.of(BookstoreApplication.class);

    void verifiesModularStructure() {

    void createModuleDocumentation() {
        new Documenter(modules).writeDocumentation();

When these tests are run, you’ll encounter errors due to the cyclic dependency:

[ERROR] Errors: 
[ERROR]   ModularityTests.verifiesModularStructure:17 » Violations - Cycle detected: Slice inventory ->


By adding these observability tools to your Spring Boot microservices or applications, you can obtain valuable performance insights, even across complex structures like those encountered with cyclic dependencies. The Spring Modulith Starter Insight, in particular, offers a modular and flexible approach to structured monitoring, irrespective of the architecture conventions in place.

Be sure to test your application’s modularity with ModularityTests and leverage the visualized traces provided by Zipkin to fully comprehend interactions across your system’s various layers.

Coffee Time!

Happy coding!

Share: Twitter LinkedIn