Hello! Welcome to what is truly the final and one of the most crucial lessons in your journey to becoming a backend developer.
In our last session, we implemented a full Continuous Deployment pipeline, automating the path from a code commit to a live application running on AWS. While this felt like a natural conclusion to the course, deploying an application is only half the battle. The other half is knowing what's happening inside it once it's running. How do you know if it's healthy? Is it fast enough? Is it about to run out of memory?
This is where observability comes in. Today, we will close this final loop by adding monitoring to our application. This lesson covers how to integrate a monitoring tool like Prometheus with Spring Boot Actuator for performance monitoring.
You will learn to set up a powerful, industry-standard monitoring stack that will give you deep insights into the health and performance of your applications.
The Monitoring Stack at a Glance
We will be working with three core components:
- Spring Boot Actuator: A Spring Boot sub-project that exposes operational information about your running application—health, metrics, environment info, and more—through a set of endpoints.
- Prometheus: An open-source monitoring and alerting toolkit. Its primary job is to periodically "scrape" (collect) metrics from configured endpoints, store them in a time-series database, and allow you to query them.
- Grafana: An open-source visualization tool. It connects to data sources like Prometheus to create rich, interactive dashboards, turning raw metrics into meaningful graphs and alerts.

Let's get started.
1. Exposing Metrics with Spring Boot Actuator
Our first step is to configure our Spring Boot application to produce metrics in a format that Prometheus can understand. This is achieved by combining Spring Boot Actuator with the Micrometer library. Micrometer acts as a metrics facade, similar to how SLF4J is a facade for logging, allowing you to instrument your code with metrics and decide at runtime which monitoring system to send them to.
Monitor a Spring Boot App Using Prometheus
The article 'Monitor a Spring Boot App Using Prometheus' on Baeldung provides a clear and concise guide for this initial setup. We will use it to add the necessary dependencies and configuration.
Please read sections 3.1 ('Adding Dependencies') and 3.2 ('Configuring the Application'). Focus on understanding the role of the spring-boot-starter-actuator and micrometer-registry-prometheus dependencies. Add them to your pom.xml. Then, update your application.properties or application.yml to expose the Prometheus endpoint.
After following the guide, your pom.xml should include these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
And your application.yml should be configured to expose the Prometheus endpoint:
management:
endpoints:
web:
exposure:
include: "prometheus,health,info" # Exposing prometheus and other useful endpoints
Now, if you run your Spring Boot application and navigate to http://localhost:8080/actuator/prometheus, you will see a text-based response. This is not meant for human eyes! It's a snapshot of all the current metrics of your application, formatted for the Prometheus scraper to consume. You'll see metrics for the JVM (memory, garbage collection), your web server (active threads), HTTP request latencies, and more.
2. Setting Up the Monitoring Stack with Docker Compose
Now that our application is exposing metrics, we need to set up Prometheus to collect them and Grafana to visualize them. Since you're familiar with Docker from our previous module, we'll use Docker Compose to spin up this entire stack with a single command.
We need two configuration files:
docker-compose.yml: Defines the Prometheus and Grafana services.prometheus.yml: Configures Prometheus, telling it where to find and scrape metrics from our Spring Boot application.
Create a new directory for these files, for example, monitoring.
1. docker-compose.yml
Create a file named docker-compose.yml with the following content:
version: '3.7'
services:
prometheus:
image: prom/prometheus:v2.44.0
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
grafana:
image: grafana/grafana:9.5.2
container_name: grafana
ports:
- "3000:3000"
restart: unless-stopped
This file defines two services: prometheus running on port 9090 and grafana on port 3000. It mounts our local prometheus.yml configuration file into the Prometheus container.
2. prometheus.yml
Create a file named prometheus.yml in the same directory:
global:
scrape_interval: 15s # How frequently to scrape targets
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['host.docker.internal:8080']
This is the key configuration. It tells Prometheus to:
- Create a job named
spring-boot-app. - Scrape the
/actuator/prometheuspath on its targets every 15 seconds. - The target is
host.docker.internal:8080.host.docker.internalis a special DNS name that resolves to the IP address of your host machine from within a Docker container. This allows the Prometheus container to reach your Spring Boot application running onlocalhost:8080.
With your Spring Boot application running locally, navigate to your monitoring directory in the terminal and run:
docker-compose up -d
This will download and start the Prometheus and Grafana containers in the background.
3. Visualizing Metrics: From Raw Data to Insight
Your full monitoring stack is now running! Let's explore it.
Exploring the Prometheus UI
First, let's verify that Prometheus is successfully collecting data from our application.
- Open your browser and go to
http://localhost:9090. - Navigate to
Status>Targetsfrom the top menu. - You should see your
spring-boot-appjob with a single endpoint. If the "State" is UP, congratulations! Prometheus is successfully scraping your application.
Monitoring and Metrics for Spring | with Prometheus - Grafana - Actuator
The following video provides a great walkthrough of the entire monitoring stack. Let's watch the segment that explains the Prometheus UI and how to run a basic query.
Watch the video from 28:43 to 30:10. This will show you how to check the target status (which you just did) and how to execute a simple PromQL (Prometheus Query Language) query like up to see the health of your scraped targets.
Creating Dashboards in Grafana
While Prometheus is great at collecting and storing data, its UI is primarily for diagnostics and querying. For visualization, we turn to Grafana.
Monitoring and Metrics for Spring | with Prometheus - Grafana - Actuator
Let's continue with the same video to see how to connect Grafana to Prometheus and, most importantly, how to quickly get a powerful dashboard up and running.
Please watch from 31:30 to 33:15. Follow these steps: Navigate to http://localhost:3000 (default login is admin/admin). Follow the video to add a new Data Source. Select Prometheus and set the URL to http://prometheus:9090. (We use prometheus as the hostname because the services are on the same Docker network). Instead of creating a dashboard from scratch, the video shows how to import a pre-built one. Go to the Grafana Dashboards marketplace, find a popular dashboard for Spring Boot (e.g., searching for "Spring Boot JVM" or dashboard ID 11378 or 4701), and import it into your Grafana instance as shown.
By importing a community dashboard, you instantly get a rich visualization of your application's performance, including:
- JVM Health: Heap memory usage, garbage collection frequency and duration, thread count.
- HTTP Server Performance: Request rate, error rate, and response times.
- System Metrics: CPU and memory usage of the process.
Test your understanding!
You configured Prometheus to scrape metrics from host.docker.internal:8080, but you configured Grafana's data source to point to http://prometheus:9090. Why the difference?
Show answer
This is an excellent question that highlights key Docker networking concepts.
-
Prometheus to Spring Boot App: The Prometheus container needs to connect to the Spring Boot application running on your host machine (i.e., outside of Docker).
host.docker.internalis the special DNS name Docker provides for containers to reach the host. -
Grafana to Prometheus: The Grafana and Prometheus containers are running within the same Docker Compose network. Docker Compose provides automatic DNS resolution between services on the same network. Therefore, the Grafana container can reach the Prometheus container simply by using its service name,
prometheus, as the hostname.
Conclusion
Congratulations on completing the final lesson! You have now set up a complete observability stack for your Spring Boot application, a skill that is absolutely essential for running reliable services in production.
Key Takeaways:
- Observability is critical: Once an application is deployed, you need tools to monitor its health and performance.
- Actuator + Micrometer: This combination is the standard way to expose application metrics from a Spring Boot application.
- Prometheus scrapes metrics: Prometheus operates on a pull model, periodically collecting data from configured endpoints.
- Grafana visualizes data: Grafana connects to data sources like Prometheus to build powerful, insightful dashboards.
- Docker Compose simplifies local setup: It's the perfect tool for running your entire monitoring stack (and other services) for local development and testing.
Your Journey as a Backend Developer
You've come a long way. You started with the fundamental building blocks of Java web development, mastered the Spring Framework to build robust REST APIs, integrated databases, secured your endpoints, wrote comprehensive tests, and finally, learned to containerize, deploy, and monitor your application using a modern CI/CD pipeline.
You now possess a solid, end-to-end skill set that forms the foundation of modern backend engineering. The journey doesn't end here. Continue to build projects, explore advanced topics like distributed tracing, delve deeper into cloud-native patterns, and never stop learning. You are well-equipped for the challenges ahead. Well done