Back to blog
Spring BootJavaDevOps

Spring Boot Best Practices for Production

Conference · 28 January 2025

Running Spring Boot in production is more than just java -jar. Here are practices that pay off: externalized config, health checks, and structured logging.

1. Externalize configuration

Never hardcode environment-specific values. Use application.yml (or .properties) and override with env vars or config server.

# application.yml – defaults
server:
  port: 8080
spring:
  datasource:
    url: ${DATABASE_URL:jdbc:postgresql://localhost:5432/app}
    username: ${DB_USER:app}
    password: ${DB_PASSWORD:}

Override in production:

export DATABASE_URL=jdbc:postgresql://db.prod:5432/app
export DB_USER=app
export DB_PASSWORD=secret
java -jar app.jar

Twelve-Factor style: config in the environment, not in the repo.

2. Health and readiness

Expose health and readiness so orchestrators know when to send traffic:

management:
  endpoints:
    web:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: when-authorized
  health:
    livenessState:
      enabled: true
    readinessState:
      enabled: true
  • Liveness – is the process alive? (restart if not.)
  • Readiness – is the app ready for traffic? (e.g. DB up, caches warm.)

Kubernetes uses these for livenessProbe and readinessProbe.

3. Structured logging

Use a structured format (e.g. JSON) so log aggregators can index and query:

logging:
  pattern:
    console: "{\"time\":\"%d{yyyy-MM-dd HH:mm:ss.SSS}\",\"level\":\"%level\",\"logger\":\"%logger\",\"msg\":\"%msg\"}\n"

In code, use SLF4J with placeholders (no string concatenation):

log.info("Request processed: requestId={}, durationMs={}", requestId, duration);

4. Graceful shutdown

Allow in-flight requests to finish before the JVM exits:

server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s

Kubernetes sends SIGTERM; with graceful shutdown, your app stops accepting new requests and waits for current ones (up to the timeout).

Summary

  • Config – env vars and externalized config; no secrets in code.
  • Health – liveness and readiness endpoints for orchestrators.
  • Logging – structured (e.g. JSON) and with placeholders.
  • Shutdown – graceful so load balancers and orchestrators can drain traffic.

These practices keep Spring Boot apps observable, configurable, and safe to deploy and scale.