Production-Ready Spring Boot: A Checklist

Your app works in development. It’ll crash in production unless you configure these 15 critical settings.


Production Deployment Checklist


1. Actuator Health Checks

Why: Kubernetes/AWS need to know when your app is ready.

management:
  endpoint:
    health:
      enabled: true
      show-details: always
  health:
    livenessState:
      enabled: true
    readinessState:
      enabled: true

2. Graceful Shutdown

Why: Prevent dropped requests during deployment.

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

3. Connection Pool Tuning

Why: Default pool size (10) is too small for production.

spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000

Rule of Thumb: max-pool-size = (num_cpu_cores * 2) + effective_spindle_count


4. Logging Configuration

Why: Debug logs in production kill performance.

logging:
  level:
    root: WARN
    com.yourcompany: INFO
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
  file:
    name: /var/log/app.log
    max-size: 10MB
    max-history: 30

5. Security Headers

Why: Protect against XSS, clickjacking, MIME sniffing.

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .headers(headers -> headers
            .contentSecurityPolicy("default-src 'self'")
            .frameOptions().deny()
            .xssProtection()
        )
        .build();
}

6. Rate Limiting

Why: Prevent API abuse and DDoS.

@Bean
RateLimiterRegistry rateLimiterRegistry() {
    return RateLimiterRegistry.of(RateLimiterConfig.custom()
        .limitForPeriod(100)  // 100 requests
        .limitRefreshPeriod(Duration.ofMinutes(1))
        .build());
}

7. Metrics Export

Why: You can’t fix what you can’t measure.

management:
  metrics:
    export:
      prometheus:
        enabled: true
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus

8. Thread Pool Configuration

Why: Default thread pools aren’t optimized for high load.

server:
  tomcat:
    threads:
      max: 200
      min-spare: 10

9. Timeout Settings

Why: Prevent hanging requests from consuming resources.

spring:
  mvc:
    async:
      request-timeout: 30000
  webflux:
    timeout: 30s

10. Compression

Why: Reduce bandwidth usage by 70%.

server:
  compression:
    enabled: true
    mime-types: text/html,text/xml,text/plain,application/json
    min-response-size: 1024

11. JVM Flags

Why: Default JVM settings aren’t production-ready.

java -Xms2G -Xmx2G \              # Set heap size
     -XX:+UseG1GC \                # Use G1 collector
     -XX:MaxGCPauseMillis=200 \    # GC pause target
     -XX:+HeapDumpOnOutOfMemoryError \  # Debug OOM
     -jar app.jar

12. Error Handling

Why: Don’t leak stack traces to users.

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleError(Exception e) {
        log.error("Unhandled exception", e);
        return ResponseEntity
            .status(500)
            .body(new ErrorResponse("Internal server error"));
    }
}

13. Database Migrations

Why: Track schema changes across environments.

spring:
  liquibase:
    enabled: true
    change-log: classpath:db/changelog/db.changelog-master.yaml

14. Feature Flags

Why: Deploy code without activating features.

@ConditionalOnProperty("feature.newDashboard.enabled")
@RestController
public class NewDashboardController {
    // Only active if feature.newDashboard.enabled=true
}

15. Distributed Tracing

Why: Debug cross-service issues.

management:
  tracing:
    sampling:
      probability: 0.1  # Sample 10% of requests
  zipkin:
    tracing:
      endpoint: http://zipkin:9411/api/v2/spans

Pre-Deployment Checklist

Setting Status
☐ Health checks configured  
☐ Graceful shutdown enabled  
☐ Connection pool tuned  
☐ Logging set to WARN/INFO  
☐ Security headers enabled  
☐ Rate limiting configured  
☐ Metrics exported  
☐ Timeouts set  
☐ Compression enabled  
☐ JVM flags optimized  
☐ Error handling implemented  
☐ Database migrations ready  
☐ Feature flags in place  
☐ Distributed tracing enabled  

Conclusion

Production readiness isn’t optional. Use this checklist before every deployment to avoid outages, performance issues, and security vulnerabilities.

Deploying to Kubernetes? Check out K8s-Native Spring Boot or Zero-Downtime Migrations.