Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 5–8 Years

Advanced Core Java

  • Advanced OOP & Design Scenarios — Interview Questions
  • Advanced Concurrency, Collections & Memory — Interview Questions
  • Modern Java Language Features & Annotations — Interview Questions
  • Class Loading, Reflection, Serialization & Idioms — Interview Questions

Java Design Patterns in Depth

  • Design Patterns Overview & Singleton — Interview Questions
  • Factory & Abstract Factory Patterns — Interview Questions
  • Builder & Prototype Patterns — Interview Questions
  • Adapter & Bridge Patterns — Interview Questions
  • Composite & Decorator Patterns — Interview Questions
  • Facade & Proxy Patterns — Interview Questions
  • Chain of Responsibility & Observer Patterns — Interview Questions
  • Strategy & Template Method Patterns — Interview Questions
  • Command Pattern — Interview Questions

Advanced Spring Boot

  • Logging, Configuration & Actuator (Advanced) — Interview Questions
  • Transactions, Multiple Datasources & Query Tuning — Interview Questions
  • Validation & REST API Design (Advanced) — Interview Questions
  • Reactive, Async & Scheduling in Spring Boot — Interview Questions
  • Deployment, High Availability, Scaling & Caching — Interview Questions
Chaturmind
← Java Interview Prep: 5–8 Years

Advanced Core Java

  • Advanced OOP & Design Scenarios — Interview Questions
  • Advanced Concurrency, Collections & Memory — Interview Questions
  • Modern Java Language Features & Annotations — Interview Questions
  • Class Loading, Reflection, Serialization & Idioms — Interview Questions

Java Design Patterns in Depth

  • Design Patterns Overview & Singleton — Interview Questions
  • Factory & Abstract Factory Patterns — Interview Questions
  • Builder & Prototype Patterns — Interview Questions
  • Adapter & Bridge Patterns — Interview Questions
  • Composite & Decorator Patterns — Interview Questions
  • Facade & Proxy Patterns — Interview Questions
  • Chain of Responsibility & Observer Patterns — Interview Questions
  • Strategy & Template Method Patterns — Interview Questions
  • Command Pattern — Interview Questions

Advanced Spring Boot

  • Logging, Configuration & Actuator (Advanced) — Interview Questions
  • Transactions, Multiple Datasources & Query Tuning — Interview Questions
  • Validation & REST API Design (Advanced) — Interview Questions
  • Reactive, Async & Scheduling in Spring Boot — Interview Questions
  • Deployment, High Availability, Scaling & Caching — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 5–8 YearsAdvanced Spring Boot
✓ FreeAdvanced· 11 min read

Logging, Configuration & Actuator (Advanced) — Interview Questions

Production logging in Spring Boot (Logback defaults, SLF4J facade, switching to Log4j2 with zero code changes, structured logs), externalised configuration benefits and risks, the real property precedence order, mixing application.yml and application.properties, migrating properties to YAML safely, and customising and securing Actuator endpoints for monitoring and management.

Published September 25, 2026


How to use this lesson

At 5–8 years of experience, "how do you log?" really means how do you run this in production? Cover:

  • structured logs, levels per package, and correlation IDs;
  • configuration precedence you can reason about when a value is "mysteriously" overridden;
  • Actuator endpoints that are useful and safe.

Q1. How do you do logging in Spring Boot?

Short answer: Spring Boot ships spring-boot-starter-logging: SLF4J as the API, and Logback as the default implementation. Out of the box, it logs to the console with a sensible pattern at INFO level. You tune it through properties first, and a logback-spring.xml file for advanced setups.

logging:
  level:
    root: INFO
    com.shopin.orders: DEBUG                  # per-package levels
    org.hibernate.SQL: DEBUG                  # see the SQL (never in production at high volume)
  file:
    name: /var/log/orders/app.log             # or log to stdout only, in containers
  structured:
    format:
      console: ecs                            # Boot 3.4+: JSON logs (ecs / logstash / gelf) for ELK, Loki, Datadog

Key points to cover:

  • Use logback-spring.xml (not logback.xml) so you can use <springProfile> and <springProperty>. Plain logback.xml is loaded before Spring, so it can't see profiles.
  • Levels can change at runtime through Actuator's /actuator/loggers endpoint, with no restart needed.
  • Correlation: Micrometer Tracing puts traceId/spanId into the MDC, so every log line can be joined to a trace. Add your own MDC keys (like orderId) in a filter, and clear them afterwards.
  • In containers, log to stdout and let the platform ship the logs. Don't manage log files in pods.

Learn it in depth → Centralized Logging

Q2. What is SLF4J?

Short answer: SLF4J (Simple Logging Facade for Java) is a logging API (a facade), not a logging engine. Your code calls org.slf4j.Logger, and a binding chosen at deployment time does the actual output: Logback, Log4j2, or java.util.logging. That's how you can swap engines without touching the code.

private static final Logger log = LoggerFactory.getLogger(OrderService.class);

log.info("Order {} placed by customer {} for {}", orderId, customerId, total);  // parameterised: no string building if INFO is off
log.warn("Payment retry {} for order {}", attempt, orderId, ex);                 // a trailing exception prints its stack trace

Key points to cover:

  • Parameterised messages ({}) avoid string concatenation cost when the level is disabled. Also, never log secrets or full personal data.
  • Bridges route other APIs into SLF4J: jul-to-slf4j, log4j-to-slf4j and jcl-over-slf4j, so every library's logs end up in one place.
  • SLF4J 2.x uses ServiceLoader providers, and adds a fluent API: log.atInfo().addKeyValue("orderId", id).log("placed").

Q3. Why is SLF4J described as "a single API, with the implementation chosen at deployment"? (Security-course variant)

Short answer: The compile-time dependency is only slf4j-api. What prints the logs is decided by which provider jar is on the classpath at runtime. Libraries should depend only on the API, so the application decides the engine, and there are no conflicting logging setups.

Common trap: having two providers on the classpath (for example Logback and log4j-slf4j2-impl). SLF4J warns and picks one. In Boot this usually means you forgot to exclude spring-boot-starter-logging.

Q4. If you switch from Logback to Log4j2, what changes in the code?

Short answer: None in the Java code, if you log through SLF4J. You only change the build and the configuration:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>   <!-- remove Logback -->
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>        <!-- add Log4j2 and its SLF4J provider -->
</dependency>

Key points to cover:

  • Replace logback-spring.xml with log4j2-spring.xml.
  • The logging.level.* properties keep working, because Boot's logging abstraction supports both engines.
  • The exclusion must apply to every starter that pulls in spring-boot-starter-logging. A global exclusion (Gradle configurations.all { exclude ... }) is easiest.
  • Code that imports Logback classes directly (ch.qos.logback.*, for example custom appenders) does need changes. That's why business code should use only the SLF4J API.

Q5. What are the benefits and considerations of externalised configuration?

Short answer:

  • Benefits: one artifact, many environments. The same jar or image is promoted from dev to QA to prod, with only the configuration changing. That follows the 12-factor principle of keeping configuration in the environment. It also lets you tweak behaviour without a rebuild (timeouts, feature flags, pool sizes).
  • Considerations:
    • Secrets: never commit them. Use environment variables or mounted secrets, Vault or AWS Secrets Manager (spring.config.import=vault://, aws-secretsmanager:), and encrypt at rest.
    • Validation: use @ConfigurationProperties with @Validated, so bad configuration fails at startup, not at 2 a.m.
    • Traceability: who changed what, and when? Keep configuration in Git, or in a configuration server with an audit trail.
    • Drift between environments.
    • Sensible defaults in application.yml.
    • Refreshing: most properties are read at startup. Changing them at runtime needs @RefreshScope or a restart.
@ConfigurationProperties(prefix = "payments")
@Validated
public record PaymentProperties(@NotNull URI gatewayUrl, @DurationMin(millis = 100) Duration timeout, @Min(0) @Max(5) int maxRetries) { }

Learn it in depth → Configuration Management

Q6. What is the order of precedence in Spring Boot configuration?

Short answer: Later sources override earlier ones. From lowest to highest precedence (a simplified version of the official list):

  1. Default properties (SpringApplication.setDefaultProperties).
  2. @PropertySource on @Configuration classes.
  3. Config data files, in this order:
    • application.properties/.yml inside the jar;
    • profile-specific files inside the jar (application-prod.yml);
    • application files outside the jar (./config/, the current directory);
    • profile-specific files outside the jar.
  4. RandomValuePropertySource (random.*).
  5. OS environment variables (SPRING_DATASOURCE_URL).
  6. Java system properties (-Dserver.port=9090).
  7. JNDI, and ServletContext/ServletConfig init parameters.
  8. SPRING_APPLICATION_JSON.
  9. Command-line arguments (--server.port=9090).
  10. Test-only sources: @TestPropertySource, and @SpringBootTest(properties=...), which are highest of all in tests.

Common trap: the source answer puts the files above environment variables. In fact, environment variables and system properties override application.yml. That's exactly why Kubernetes and Docker can set SPRING_PROFILES_ACTIVE or SERVER_PORT without rebuilding.

Key points to cover:

  • To debug "where did this value come from?", use /actuator/env/{property}. It shows every source that defines the property, and which one wins.

Q7. Can you use both application.yml and application.properties? How are they prioritised?

Short answer: Yes. Boot loads both and merges them. If the same key is in both in the same location, .properties wins over .yml. Keys that appear in only one file are used as-is.

Key points to cover:

  • Don't mix the formats in one project. It confuses everyone about where a value lives. Pick one (YAML is common for its hierarchy), and use profiles and external sources for overrides.
  • Location and profile precedence (Q6) still apply above the format rule. For example, an external application.yml beats a packaged application.properties.

Q8. You're migrating an application from properties files to YAML. What are the steps and considerations?

Short answer:

  1. Convert each file (application.properties to application.yml, application-prod.properties to application-prod.yml), turning dotted keys into nested maps. An IDE or a converter tool helps.
  2. Watch the YAML pitfalls:
    • Indentation is significant.
    • Unquoted values get type-converted: on/off/yes/no can become booleans in YAML 1.1, and a leading 0 can make a value octal. Quote passwords and IDs like "0123".
    • Special characters (:, #, *) need quotes.
    • Lists become - item, or [a, b].
  3. Multi-document files: you can put several profiles in one YAML file, separated by ---, with spring.config.activate.on-profile: prod. The old spring.profiles: key is deprecated.
  4. @PropertySource doesn't support YAML out of the box. Keep those files as .properties, or write a YAML PropertySourceFactory.
  5. Verify equivalence: compare the resolved Environment before and after (/actuator/env, or a test that asserts the key values). Run the integration tests for each profile.
  6. Delete the old .properties files in the same change, so the .properties-wins rule can't silently keep old values.

Common trap: the migration "works", but a stale application.properties is still on the classpath and overriding the new YAML values.

Q9. How do you customise Actuator endpoints?

Short answer:

  • Exposure:
    • Over HTTP, only health is exposed by default.
    • Expose deliberately: management.endpoints.web.exposure.include=health,info,metrics,prometheus.
    • Avoid * in production.
  • Paths and ports:
    • management.endpoints.web.base-path=/manage.
    • Run Actuator on a separate management port (management.server.port=8081) that's only reachable internally.
  • Security: protect everything except health and info with Spring Security (an EndpointRequest matcher), and sanitise env and configprops values (management.endpoint.env.show-values=WHEN_AUTHORIZED).
  • Health:
    • Health groups for Kubernetes: /actuator/health/liveness and /actuator/health/readiness.
    • show-details=when-authorized.
    • Custom HealthIndicators.
  • Custom endpoints:
@Component
@Endpoint(id = "featureflags")
public class FeatureFlagsEndpoint {
    private final FeatureFlagStore store;
    FeatureFlagsEndpoint(FeatureFlagStore store) { this.store = store; }

    @ReadOperation  public Map<String, Boolean> all() { return store.all(); }                  // GET  /actuator/featureflags
    @ReadOperation  public Boolean one(@Selector String name) { return store.get(name); }      // GET  /actuator/featureflags/{name}
    @WriteOperation public void set(@Selector String name, boolean enabled) { store.set(name, enabled); }   // POST
    @DeleteOperation public void reset(@Selector String name) { store.reset(name); }           // DELETE
}
  • Use @WebEndpoint for HTTP-only endpoints. Use **InfoContributor**s to add build, Git or custom data to /info.

Learn it in depth → Health Checks

Q10. How can Actuator be used for application monitoring and management?

Short answer:

  • Health: /health and its liveness/readiness groups drive load balancer and Kubernetes probes. Database, disk, broker and custom indicators decide whether the instance takes traffic.
  • Metrics: /metrics and /prometheus, backed by Micrometer. JVM, HTTP (http.server.requests with percentiles), datasource pool, cache, executor and custom business metrics are scraped by Prometheus, and shown in Grafana with alerts.
  • Diagnostics:
    • /loggers: change log levels live;
    • /threaddump and /heapdump: investigate hangs and leaks;
    • /env and /configprops: resolved configuration;
    • /beans, /conditions (why an auto-configuration did or didn't apply), /mappings;
    • /scheduledtasks, /caches, /flyway or /liquibase.
  • Tracing with Micrometer Tracing (OpenTelemetry or Brave), exporting to Zipkin, Jaeger or Tempo.
  • Management actions: clearing caches, /shutdown (disabled by default), and custom write operations (like the feature flags above). Spring Boot Admin gives a UI over all of this.

Common trap: exposing /heapdump or /env publicly. A heap dump contains secrets and user data. Lock it down, or don't expose it at all.

Learn it in depth → Metrics & Monitoring

Follow-up questions this topic invites — and their answers

Q: How do you add a correlation ID to every log line for a request? A: With Micrometer Tracing, traceId is already in the MDC. Include %X{traceId} in the log pattern, or use structured logging. For a custom ID, a OncePerRequestFilter reads or creates the X-Correlation-Id header, calls MDC.put, and clears the MDC in finally. Propagate it to asynchronous threads with a TaskDecorator.

Q: What's the cost of DEBUG logging in production? A: CPU for formatting and I/O, larger log volumes and storage bills, and possible leakage of sensitive data. Enable it temporarily and per package through /actuator/loggers, and turn it off afterwards.

Q: How do you keep secrets out of application.yml? A: Reference placeholders (${DB_PASSWORD}) resolved from environment variables or mounted Kubernetes secrets, or use spring.config.import with Vault, AWS Secrets Manager or Parameter Store, or a configuration server with encrypted values. Rotate the secrets, and never log the resolved values.

Q: What does /actuator/conditions help you debug? A: The auto-configuration report: which auto-configurations matched or didn't, and why (for example "@ConditionalOnMissingBean found an existing DataSource"). It's invaluable when a bean you expected isn't created. --debug prints the same report at startup.

Previous

Command Pattern — Interview Questions

Next

Transactions, Multiple Datasources & Query Tuning — Interview Questions

AI Tutor

Lesson: Logging, Configuration & Actuator (Advanced) — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.