Monitoring with Actuator

Reviewed & published by Brayan K

Spring Boot Actuator bolts production-ready endpoints onto your app — /actuator/health, /actuator/metrics, /actuator/info — with Micrometer collecting metrics you can export anywhere.

Part of the free Java course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

Before You Start

You should be comfortable building a Spring Boot app and tweaking its configuration and profiles. Knowing a little about HTTP endpoints and JSON helps when reading the responses.

What You'll Learn

The Big Idea — The Dashboard of Your Application

💡 Analogy: Actuator is the dashboard and warning lights of your application, like a car's instrument cluster. /actuator/health is the big green "all systems go" light — and if the oil, brakes, or engine (any component) fails, it flips to red. /actuator/metrics is the set of gauges: speed, RPM, fuel — live numbers about how hard the engine is working. /actuator/info is the little plate showing the model and build. And just as you don't let strangers pop the hood and read the diagnostics port, you lock down the sensitive endpoints in production.

You don't build the dashboard yourself — Actuator wires it in; you just choose which gauges to show and to whom.

1️⃣ /health — Aggregated Status

The health endpoint combines many component checks into one status: if any indicator is DOWN, the whole app reports DOWN. The plain-Java model below shows that aggregation rule.

import java.util.*;

public class Main {
    // /actuator/health AGGREGATES many component checks into one status: if ANY
    // component is DOWN, the whole app is DOWN. We model that aggregation in
    // plain Java so the health-endpoint logic is concrete.
    interface HealthIndicator { String name(); boolean up(); }

    static String overall(List<HealthIndicator> checks) {
        boolean allUp = checks.stream().allMatch(HealthIndicator::up);
        return allUp ? "UP" : "DOWN";
    }

    public static void main(String[] args) {
        List<HealthIndicator> checks = List.of(
            indicator("db",   true),
            indicator("disk", true),
            indicator("mail", false)   // one downstream is unhealthy
        );

        System.out.println("overall: " + overall(checks));
        for (HealthIndicator h : checks) {
            System.out.println("  " + h.name() + ": " + (h.up() ? "UP" : "DOWN"));
        }
    }

    static HealthIndicator indicator(String n, boolean up) {
        return new HealthIndicator() {
            public String name() { return n; }
            public boolean up()  { return up; }
        };
    }
}

2️⃣ /metrics — Counters and Gauges

Metrics are collected by Micrometer. The core meter types are counters (ever-increasing totals, like request counts) and gauges (live values, like active sessions). The demo builds tiny versions to show what a registry holds.

import java.util.*;
import java.util.concurrent.atomic.*;

public class Main {
    // Micrometer's two core meter types: COUNTERS (monotonic totals) and GAUGES
    // (current values). Actuator's /actuator/metrics surfaces exactly these. We
    // build tiny versions to show what a metric registry actually holds.
    static class Counter {
        private final AtomicLong count = new AtomicLong();
        void increment() { count.incrementAndGet(); }
        long value() { return count.get(); }
    }

    public static void main(String[] args) {
        Map<String, Counter> registry = new LinkedHashMap<>();
        Counter requests = new Counter();
        registry.put("http.server.requests", requests);

        // Simulate handling some requests.
        for (int i = 0; i < 5; i++) requests.increment();

        // A gauge reads a live value (e.g. active sessions).
        int activeSessions = 3;

        System.out.println("counter http.server.requests = " + requests.value());
        System.out.println("gauge   active.sessions       = " + activeSessions);
        System.out.println("registry has metrics: " + registry.keySet());
    }
}

3️⃣ Exposing Endpoints

By default only health (and info) are exposed over HTTP. You opt into more with management.endpoints.web.exposure.include and can enrich /info with build metadata.

management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=when-authorized
# application.properties — exposing Actuator endpoints (needs
# spring-boot-starter-actuator on the classpath).

# By default only 'health' (and 'info') are exposed over HTTP. Opt in to more:
management.endpoints.web.exposure.include=health,info,metrics

# Show full health details (component breakdown) — guard this in production!
management.endpoint.health.show-details=when-authorized

# Populate /actuator/info from build + git metadata.
management.info.env.enabled=true
info.app.name=Orders API
info.app.version=1.4.0

# Then, with the app running, these URLs work:
#   GET /actuator/health   -> {"status":"UP"}
#   GET /actuator/info     -> {"app":{"name":"Orders API","version":"1.4.0"}}
#   GET /actuator/metrics  -> {"names":["http.server.requests", ...]}
#   GET /actuator/metrics/http.server.requests -> measurements for that metric

4️⃣ Adding a Custom HealthIndicator

Implement HealthIndicator to fold your own check (a downstream service, a queue, a license) into /actuator/health — the same aggregation you saw in section 1.

🧠 Quick Recall

Predict before you peek.

Answer: DOWN — the overall status aggregates components and fails if any one fails.

Answer: Micrometer — a vendor-neutral facade that exports to many monitoring backends.

Answer: add it to management.endpoints.web.exposure.include (it isn't exposed by default).

🎯 YOUR TURN — Health Aggregation

Write overall(components) returning "UP" only when every component is up.

import java.util.*;

public class Main {
    // YOUR TURN: implement the health AGGREGATION rule.
    // Write overall(Map<String,Boolean> components) that returns "UP" only when
    // EVERY component is up, otherwise "DOWN".
    //
    // Expected output:
    //   all up   -> UP
    //   one down -> DOWN

    // static String overall(Map<String,Boolean> components) { ... }

    public static void main(String[] args) {
        // System.out.println("all up   -> " + overall(Map.of("db", true, "disk", true)));
        // System.out.println("one down -> " + overall(Map.of("db", true, "disk", false)));
    }
}

🧩 MINI-CHALLENGE — A Tiny Metrics Registry

Build a named-counter registry like Micrometer: increment by name, then print all metrics sorted.

import java.util.*;
import java.util.concurrent.atomic.*;

public class Main {
    // MINI-CHALLENGE: a tiny metrics registry like Micrometer. Support named
    // counters: increment a counter by name (creating it on first use) and then
    // expose all metric names and values, sorted by name.
    //
    // Expected output:
    //   logins=2
    //   orders=3

    static Map<String, AtomicLong> registry = new TreeMap<>();

    static void increment(String name) {
        // get-or-create the counter for 'name' and increment it
    }

    public static void main(String[] args) {
        // increment "orders" 3 times and "logins" twice
        // then print each "name=value" sorted
    }
}

Common Errors

Pro Tips

📋 Quick Reference

ConceptSyntax / ideaNote
starterspring-boot-starter-actuatorAdds endpoints
health/actuator/healthUP/DOWN aggregate
metrics/actuator/metricsBrowse meters
info/actuator/infoApp/build details
metrics libMicrometerFacade to backends
countermonotonic totalOnly increases
gaugecurrent valueUp and down
exposeexposure.include=health,info,metricsOpt in
custom checkimplements HealthIndicatorAdds a component
securelimit + protect endpointsProduction safety

📚 Resources / Keep Learning

🎉 Lesson Complete!

You now know what Actuator adds, how /health aggregates component checks, how Micrometer collects counters and gauges behind /metrics, how to expose endpoints with exposure.include, and why sensitive endpoints must be secured in production.

Practice quiz

What does Spring Boot Actuator provide?

  • Production-ready endpoints for monitoring and managing your app
  • A UI framework
  • A build tool
  • A database driver

Answer: Production-ready endpoints for monitoring and managing your app. Actuator exposes ready-made endpoints (health, metrics, info, and more) so you can monitor and manage a running application.

Which Actuator endpoint reports whether the app is up?

  • /actuator/shutdown
  • /actuator/health
  • /actuator/beans
  • /actuator/env

Answer: /actuator/health. The /actuator/health endpoint reports overall health (UP/DOWN) and aggregates component health indicators.

Which endpoint exposes application metrics?

  • /actuator/info
  • /actuator/threaddump
  • /actuator/metrics
  • /actuator/loggers

Answer: /actuator/metrics. /actuator/metrics lists metric names; /actuator/metrics/{name} shows a specific metric's measurements.

What is the /actuator/info endpoint for?

  • Listing all beans
  • Shutting down the app
  • Streaming logs
  • Showing arbitrary application info (build, git, custom details)

Answer: Showing arbitrary application info (build, git, custom details). /actuator/info surfaces general, customizable application information such as build and git details.

Which library backs Actuator's metrics collection?

  • Log4j
  • Micrometer
  • Jackson
  • Hibernate

Answer: Micrometer. Micrometer is the metrics facade Actuator uses; it can export to Prometheus, Datadog, and other monitoring systems.

By default in recent Spring Boot, which endpoint is exposed over HTTP?

  • All endpoints
  • None
  • Only health (and info)
  • Only shutdown

Answer: Only health (and info). For safety, only a minimal set (health, and info) is exposed over HTTP by default; others must be opted in.

How do you expose more endpoints over HTTP?

  • management.endpoints.web.exposure.include
  • server.expose=all
  • spring.actuator.on=true
  • endpoints.show()

Answer: management.endpoints.web.exposure.include. Set management.endpoints.web.exposure.include (e.g. health,info,metrics or *) in your configuration.

Why should you secure or limit Actuator endpoints in production?

  • They are slow
  • Some reveal sensitive internals (env, configprops, heapdump)
  • They use too much memory always
  • They break JSON

Answer: Some reveal sensitive internals (env, configprops, heapdump). Endpoints like env, configprops, and heapdump can leak sensitive data, so restrict exposure and protect them.

Micrometer acts as...

  • a database
  • a web server
  • a vendor-neutral facade so the same metrics export to many backends
  • a serializer

Answer: a vendor-neutral facade so the same metrics export to many backends. Like SLF4J for logging, Micrometer is a facade letting you instrument once and export to Prometheus, Datadog, etc.

A custom HealthIndicator lets you...

  • change the server port
  • rename endpoints
  • disable metrics
  • contribute a component's health (e.g. a downstream service) to /actuator/health

Answer: contribute a component's health (e.g. a downstream service) to /actuator/health. Implementing HealthIndicator adds your own UP/DOWN check that is aggregated into the overall health response.

Continue this course

Frequently asked questions

What is Spring Boot Actuator and why use it?

Actuator is a Spring Boot module that adds production-ready endpoints for monitoring and managing a live application. Once you add spring-boot-starter-actuator, you get ready-made HTTP (and JMX) endpoints such as /actuator/health, /actuator/metrics, /actuator/info, /actuator/env, and more — no code required. It saves you from hand-building health checks and metrics plumbing, and it integrates with monitoring systems, so operators can see at a glance whether the app is healthy and how it is behaving under load.

What does the /actuator/health endpoint actually report?

The health endpoint reports an overall status — typically UP or DOWN — that aggregates a set of health indicators. Spring Boot ships indicators for common components (datasource, disk space, message brokers, and so on), and the overall status is DOWN if any contributing component is DOWN. You can show a detailed breakdown of each component (gated behind configuration for safety), and you can add your own custom HealthIndicator to fold a downstream dependency's status into the result. This is what load balancers and orchestrators often probe to decide if an instance should receive traffic.

How does Actuator collect metrics, and what is Micrometer?

Actuator's metrics are powered by Micrometer, a vendor-neutral metrics facade — think of it as SLF4J but for metrics. You (and Spring Boot's auto-configuration) record meters such as counters (monotonically increasing totals like request counts), gauges (current values like active connections), and timers (latency distributions). Micrometer then exports those same meters to whatever monitoring backend you configure — Prometheus, Datadog, New Relic, and others — so you instrument once and ship the data anywhere. The /actuator/metrics endpoint lets you browse them over HTTP.

How do I expose Actuator endpoints, and which are exposed by default?

For safety, recent Spring Boot exposes only a minimal set over HTTP by default (health, and info). To expose more, set management.endpoints.web.exposure.include in your configuration — for example health,info,metrics, or * for everything (not advisable in production). You can also change the base path or move endpoints to a separate management port. The principle is least exposure: turn on only what you need, because some endpoints are powerful or sensitive.

Why must I be careful with Actuator endpoints in production?

Several endpoints can reveal internal details or perform powerful operations: /actuator/env and /actuator/configprops can expose configuration (potentially including secrets), /actuator/heapdump produces a memory dump, /actuator/threaddump shows thread state, and /actuator/loggers can change log levels at runtime. If these are open to the public, they become an information-disclosure or denial-of-service risk. Best practice is to expose only the endpoints you need, secure them with Spring Security, and ideally serve them on an internal-only management port or network.

Related lessons