Skip to content
Spring Boot sb production 4 min read

Spring Boot Actuator

Spring Boot Actuator turns your application into a manageable, observable service by exposing a set of built-in HTTP (and JMX) endpoints for health, metrics, configuration, and runtime introspection. It is the foundation for operating Spring Boot in production: load balancers poll its health endpoint, monitoring systems scrape its metrics, and operators inspect beans, mappings, and log levels without redeploying.

Add a single starter and the endpoints appear automatically — you decide which ones to expose and how to secure them.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

In This Section

The endpoints

Each endpoint exposes a slice of runtime state under the /actuator base path. The most commonly used ones:

EndpointPathPurpose
health/actuator/healthApplication and dependency health status
info/actuator/infoArbitrary application info (build, git, custom)
metrics/actuator/metricsMicrometer meters (memory, CPU, HTTP, JDBC)
env/actuator/envResolved Environment properties
loggers/actuator/loggersView and change log levels at runtime
mappings/actuator/mappingsAll @RequestMapping routes
beans/actuator/beansEvery bean in the application context
configprops/actuator/configprops@ConfigurationProperties beans
threaddump/actuator/threaddumpJVM thread dump
shutdown/actuator/shutdownGraceful shutdown (disabled by default)

By default only health is exposed over HTTP. Everything else must be explicitly opted in.

Exposing endpoints

Control which endpoints are reachable over the web with management.endpoints.web.exposure.

management:
  endpoints:
    web:
      exposure:
        include: health, info, metrics, loggers, mappings
        # exclude: env   # remove a single endpoint from a wildcard include
      base-path: /actuator   # default; change to /manage if you like
  endpoint:
    health:
      show-details: when-authorized
    shutdown:
      access: read-only   # 'unrestricted' enables POST shutdown

Warning: include: "*" exposes every endpoint, including env, heapdump, and threaddump, which leak secrets and internals. Never use a wildcard on a public-facing port.

Inspecting the running app

With the endpoints exposed, a simple GET returns JSON.

curl http://localhost:8080/actuator/health

Output:

{
  "status": "UP",
  "components": {
    "db": { "status": "UP", "details": { "database": "PostgreSQL", "validationQuery": "isValid()" } },
    "diskSpace": { "status": "UP", "details": { "total": 250790436864, "free": 91234508800, "threshold": 10485760 } },
    "ping": { "status": "UP" }
  }
}

The info endpoint is empty until you populate it. Build and git metadata are added automatically when the relevant plugins run, plus any custom info.* properties.

info:
  app:
    name: Order Service
    version: 2.4.1
management:
  info:
    git:
      mode: full
    env:
      enabled: true

Output of /actuator/info:

{
  "app": { "name": "Order Service", "version": "2.4.1" },
  "git": { "branch": "main", "commit": { "id": "a1b2c3d", "time": "2026-06-13T09:12:04Z" } }
}

Changing log levels at runtime

The loggers endpoint can read and change a logger’s level without a restart — invaluable for debugging production incidents.

# Inspect the current level
curl http://localhost:8080/actuator/loggers/com.example.orders

# Raise it to DEBUG on the fly
curl -X POST http://localhost:8080/actuator/loggers/com.example.orders \
  -H 'Content-Type: application/json' \
  -d '{"configuredLevel":"DEBUG"}'

Securing Actuator

Actuator endpoints are HTTP routes, so they are secured like any other route with Spring Security. The cleanest production setup runs management on a separate port and locks the endpoints behind a role.

management:
  server:
    port: 9001            # isolate management traffic from the app port
  endpoints:
    web:
      exposure:
        include: health, info, metrics, prometheus
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class ActuatorSecurityConfig {

    @Bean
    SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
        http
            .securityMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(EndpointRequest.to("health", "info")).permitAll()
                .anyRequest().hasRole("ACTUATOR"))
            .httpBasic(org.springframework.security.config.Customizer.withDefaults());
        return http.build();
    }
}

Tip: EndpointRequest.toAnyEndpoint() matches the configured base path automatically, so the filter chain keeps working even if you change base-path or the management port.

Note: Keep /health and /info public so probes and dashboards work without credentials, but require a role for everything that reveals internals (env, beans, loggers, threaddump).

Best Practices

  • Expose only the endpoints you actually use; never wildcard on a public port.
  • Run management on a separate management.server.port and firewall it to your monitoring network.
  • Set health.show-details: when-authorized so anonymous probes see only UP/DOWN.
  • Secure non-trivial endpoints with a SecurityFilterChain scoped via EndpointRequest.
  • Add git and build info so deployed versions are traceable from /actuator/info.
Last updated June 13, 2026
Was this helpful?