Configurationhard8+ years

Two of your own `@Configuration` classes, in different modules, each declare `@Bean @ConditionalOnMissingBean PricingClient pricingClient()` as a defensive default, expecting exactly one to win. In practice, which one wins is inconsistent between builds. Why is relying on `@ConditionalOnMissingBean` between two of your own configuration classes fundamentally different from relying on it against Spring Boot's auto-configuration, and what should you do instead?

@ConditionalOnMissingBean works reliably against Spring Boot's own auto-configuration because Boot guarantees your configuration is always processed before auto-configuration — that ordering is a documented, stable contract, which is exactly why defining your own DataSource silently and correctly replaces Boot's default instead of colliding with it. Between two configuration classes you wrote yourself, there is no such guaranteed order: which one the container happens to process first is an implementation detail of classpath scanning and configuration processing order, not a contract Spring promises to keep stable, so 'whichever one gets processed first wins, the other backs off' becomes a race with an unpredictable, build-to-build-inconsistent winner. The fix isn't a more clever condition — it's making the choice explicit: @Primary on the one that should genuinely be the default, or removing the duplication entirely so only one configuration class defines the bean.

The lesson behind it →
More on Configuration