Configuration is the thermostat of a microservice: if the setting is wrong, the whole room feels broken. Interviewers love this question because it tests whether you can keep code flexible without hard-coding environment details.
Question: What is configuration management in Spring Boot microservices?
Answer: Configuration management means keeping settings outside the code so the same service can run in dev, test, and prod with different URLs, timeouts, credentials, and feature flags. Spring Boot reads those values from property files, environment variables, command-line args, and optionally a central config server, then binds them into beans. The core idea is simple: code stays the same, configuration changes per environment.
Interview-Ready Answer: In Spring Boot microservices, I manage configuration by externalizing settings instead of hard-coding them. I usually bind related settings with @ConfigurationProperties, use profiles like dev and prod, and keep secrets separate from normal config. In larger systems, I also use a centralized source like Spring Cloud Config so every service can share consistent values, while environment variables and command-line args still override safely when needed.
In Spring Boot, a property source is just a place where config can come from: application.yml, application-prod.yml, environment variables, command-line args, or a remote config service. Spring keeps these sources in an ordered list, so higher-priority values override lower-priority ones. A binder is the part that maps raw text values into Java objects, and relaxed binding means Spring can match checkout.request-timeout-ms, checkout.requestTimeoutMs, and CHECKOUT_REQUEST_TIMEOUT_MS to the same field.
Environment, which is the object that holds all config values.spring.config.import=configserver:.dev, test, or prod. That choice changes which files and values are loaded.@ConfigurationProperties, Spring binds a whole group of related settings at once, which is safer than scattering single values through the code.@Validated plus constraints like @Min or @NotBlank. This is a big win because bad config fails early at startup instead of failing under traffic.| Option | Best for | Watch out |
|---|---|---|
@Value | One-off value | Scattered, weak validation |
@ConfigurationProperties | Grouped settings | Needs a config class |
| Spring Cloud Config | Many services | Remote dependency |
Rule of thumb: use @ConfigurationProperties for most application settings because it keeps related values together, is easier to test, and is safer to validate. Use a config server when many services must share the same source of truth, such as gateway routes, API endpoints, and feature flags.
In Spring Boot 2.4 and newer, the Config Data API changed how config is loaded; modern apps usually prefer spring.config.import instead of relying on the old bootstrap context. That detail matters in interviews because older examples on the internet can be outdated. Binding itself is roughly O(n) in the number of properties being bound, which is small in practice; the bigger cost is a remote config call, which often adds about 50-300 ms to startup depending on network and server load. For microservices, common starting values are around 2s request timeouts, 3 retries, and pool sizes in the 10-20 range, then tuned with real traffic.
fail-fast=true makes the service stop immediately, which is often safer for payments than booting with partial config.Imagine an ecommerce checkout service. It needs payment.gateway.base-url, payment.request-timeout-ms, and payment.retry-attempts. The team keeps these in a config repo and deploys the same jar to every environment. Production points to the real payment gateway, staging points to a sandbox, and dev uses local mocks. One day, someone activates the wrong profile, so prod loads application-dev.yml and starts sending traffic to the sandbox URL.
What goes wrong: users click Pay and see a spinner, then a generic failure. Logs fill up with 404s or TLS errors from the wrong endpoint, and retries make the problem louder by multiplying the traffic. If the team uses Spring Cloud Config with a bad timeout value, they may also see ReadTimeoutException or a startup failure if validation catches the mistake. The user impact is simple and painful: orders are abandoned, revenue drops, and support gets flooded with complaints.
Why configuration management matters here: the bug is not in the payment logic; it is in how environment-specific values are delivered and validated. Good config management lets the team fix the value once, roll it out safely, and avoid rebuilding the application for every environment change.
package com.example.configurationmanagement;\n\nimport java.math.BigDecimal;\n\nimport jakarta.validation.constraints.Max;\nimport jakarta.validation.constraints.Min;\nimport jakarta.validation.constraints.NotBlank;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.server.ResponseStatusException;\n\n@SpringBootApplication\n@EnableConfigurationProperties(ConfigurationManagementApplication.CheckoutProperties.class)\npublic class ConfigurationManagementApplication {\n\n public static void main(String[] args) {\n SpringApplication.run(ConfigurationManagementApplication.class, args);\n }\n\n @Bean\n CommandLineRunner showStartupConfig(CheckoutProperties props) {\n return args -> System.out.println(\n "Loaded checkout config -> currency=" + props.currency() +\n ", timeoutMs=" + props.requestTimeoutMs() +\n ", retries=" + props.retryAttempts());\n }\n\n @ConfigurationProperties(prefix = "checkout")\n @Validated\n public record CheckoutProperties(\n @NotBlank String currency,\n @Min(100) @Max(5000) Integer requestTimeoutMs,\n @Min(1) @Max(10) Integer retryAttempts) {\n\n public CheckoutProperties {\n // Defaults keep the app runnable in a clean dev environment.\n // If ops ships a bad value like 50ms, validation stops startup before traffic sees it.\n currency = (currency == null || currency.isBlank()) ? "USD" : currency;\n requestTimeoutMs = requestTimeoutMs == null ? 2000 : requestTimeoutMs;\n retryAttempts = retryAttempts == null ? 3 : retryAttempts;\n }\n }\n\n @RestController\n @RequestMapping("/pricing")\n public static class PricingController {\n private final PricingService pricingService;\n\n public PricingController(PricingService pricingService) {\n this.pricingService = pricingService;\n }\n\n @GetMapping("/quote")\n public QuoteResponse quote(@RequestParam String user, @RequestParam BigDecimal amount) {\n if (amount.signum() < 0) {\n // This is the runtime failure path: bad input is rejected immediately and clearly.\n throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "amount must be >= 0");\n }\n return pricingService.quote(user, amount);\n }\n }\n\n @org.springframework.stereotype.Service\n public static class PricingService {\n private final CheckoutProperties props;\n\n public PricingService(CheckoutProperties props) {\n this.props = props;\n }\n\n public QuoteResponse quote(String user, BigDecimal amount) {\n BigDecimal fee = new BigDecimal("1.25");\n BigDecimal total = amount.add(fee);\n return new QuoteResponse(\n user,\n props.currency(),\n amount,\n fee,\n total,\n props.requestTimeoutMs(),\n props.retryAttempts());\n }\n }\n\n public record QuoteResponse(\n String user,\n String currency,\n BigDecimal amount,\n BigDecimal fee,\n BigDecimal total,\n int requestTimeoutMs,\n int retryAttempts) {\n }\n}@ConfigurationProperties different from @Value? @ConfigurationProperties binds a whole group of related settings into one object, which is easier to validate and test. @Value is fine for one simple value, but it becomes messy when you have many fields.dev or prod. When a profile is active, Spring loads matching config files such as application-prod.yml and can switch beans or values for that environment.@RefreshScope on beans that should be reloaded. The catch is that runtime refresh is not free; it can create temporary inconsistency, so use it for values like feature flags more than for core infrastructure.spring.config.import=configserver:. That is why old bootstrap.yml examples may not match current projects.application-prod.yml load automatically? No. It loads only when the prod profile is active. Many candidates forget that the file name is not enough; the profile must be turned on too.@RefreshScope or a custom refresh strategy. Without that, the app keeps the old value until restart.Common Mistakes:
@Value for large config objects. Fix: switch to @ConfigurationProperties so settings stay grouped and testable.spring.profiles.active intentionally in each deployment target.Memory Hook: Think of a microservice like a restaurant: the code is the kitchen layout, but configuration is today’s menu, prices, and supplier list. Same restaurant, different day, different setup.
Cheat Sheet:
@ConfigurationProperties for grouped settings.dev and prod.Practice Tasks:
checkout.discount-enabled and use it in the response.prod profile file and override the currency and timeout.checkout.request-timeout-ms=50 and observe startup validation failure.