skip to content

What is @Fallback (Spring 6.2), how does it differ from @Primary, and when would a library use it?

level: principalimportance: nice to knowfreq 20%

answer

  1. Spring 6.2 / Boot 3.4
  2. opposite of @Primary
  3. dropped whenever a regular candidate exists
  4. library default, app overrides for free
  5. cleaner than @ConditionalOnMissingBean

basics

~20 s

@Fallback (Spring 6.2) marks a bean as a last-resort candidate: it's used only when no regular bean of that type exists. It's the opposite of @Primary — @Primary says 'prefer me', @Fallback says 'use me only if there's nothing else'.

solid answer

~40 s

@Fallback, added in Spring Framework 6.2, marks a bean as a fallback autowire candidate. During resolution Spring first sets aside fallback beans: if any regular (non-fallback) candidate matches the type, all fallbacks are discarded before @Primary/@Priority/name matching run — so a regular bean wins automatically, no @Primary needed. Fallbacks are only considered when no regular candidate exists. This is the inverse of @Primary, which nominates a preferred winner among competing regular beans. The killer use case is library and auto-configuration design: a framework ships a sensible default bean annotated @Fallback; an application that defines its own bean of that type transparently overrides it, with no NoUniqueBeanDefinitionException and without the application needing to add @Primary or a qualifier. It replaces the older, clumsier @ConditionalOnMissingBean-style patterns for many cases with a cleaner, first-class DI mechanism.

code

java · 21 lines
java
import org.springframework.context.annotation.Fallback;

@Configuration
class LibraryAutoConfig {
    // Shipped by a library: a sensible default, easily overridden
    @Bean
    @Fallback
    Clock clock() {
        return Clock.systemUTC();
    }
}

@Configuration
class AppConfig {
    // The application's own bean is 'regular', so it wins automatically —
    // no @Primary needed, no NoUniqueBeanDefinitionException.
    @Bean
    Clock clock() {
        return Clock.fixed(Instant.parse("2026-01-01T00:00:00Z"), ZoneOffset.UTC);
    }
}

go deeper

for a junior

Likely unaware; fine to not know this newer annotation.

for a middle

Can state it's the opposite of @Primary at a high level.

for a senior

Explains its place in resolution and the library-default use case.

for a principal

Compares it to @ConditionalOnMissingBean and reasons about override ergonomics and version gating for shared modules.

## What @Fallback is `@Fallback` (`org.springframework.context.annotation.Fallback`), introduced in **Spring Framework 6.2** (late 2024, shipped with Spring Boot 3.4), marks a bean definition as a **fallback candidate for autowiring** — a bean to be injected *only when no other regular candidate is available* for the required type. It is the **logical opposite of `@Primary`**: | Annotation | Meaning | Effect when multiple beans match | |---|---|---| | `@Primary` | "prefer me" | wins the tie among **regular** candidates | | `@Fallback` | "use me only if nothing else" | removed from contention whenever any regular candidate exists | ## Where it sits in resolution During candidate resolution Spring partitions matches into **regular** and **fallback** beans. If there is **at least one regular candidate**, **all fallback candidates are dropped** *before* `@Primary`, `@Priority`, and bean-name matching are considered. Only when the candidate set contains **no** regular beans do the fallback beans get to compete (and among themselves, the normal `@Primary`/`@Priority`/name rules then apply). So: - 1 regular + 1 fallback → regular wins, **no `@Primary` required, no ambiguity exception**. - 0 regular + 1 fallback → fallback is injected. - 0 regular + 2 fallbacks → normal disambiguation among the fallbacks (may need `@Primary`/qualifier). ## Why it exists — library/auto-config ergonomics Before `@Fallback`, the idiomatic way for a framework to provide an overridable default was `@ConditionalOnMissingBean` (a Spring Boot construct evaluated at configuration time). That works but couples the default to Boot's conditional machinery and has ordering subtleties. `@Fallback` is a **core-container** mechanism that expresses the same intent at the DI level: ```java // Inside a library / auto-configuration @Bean @Fallback Clock defaultClock() { return Clock.systemUTC(); } ``` An application can now simply declare its own `Clock` bean; because the app's bean is *regular* and the library's is *fallback*, the app's wins automatically — no clash, no need for the app to add `@Primary`, no need for the library to guess. ## Contrast with @Primary in a library If the library used `@Primary` for its default instead, and the application also defined a `@Primary` bean, you'd get **two primaries → `NoUniqueBeanDefinitionException`**. If the library's bean were `@Primary` and the app's were plain, the **library's** default would wrongly win. `@Fallback` inverts the default correctly: the application's plain bean beats the library's fallback with zero ceremony. ## Edge cases and notes - **Fallback + collection injection:** collections still gather all matches; the fallback concept applies to single-value resolution. - **Multiple fallbacks, no regular:** they compete normally, so you may still mark one `@Primary` or qualify. - **@Fallback on @Bean methods and @Component classes** both work. - **Version gate:** requires Spring Framework 6.2+ / Spring Boot 3.4+. On older versions the annotation doesn't exist — reach for `@ConditionalOnMissingBean` instead. - **Not a replacement for qualifiers:** if consumers must *choose* among several intentional implementations, qualifiers/`@Primary` still express that; `@Fallback` is specifically for "default unless overridden." ## When to use it Reach for `@Fallback` when you author a **default bean meant to be optionally replaced** by downstream code — libraries, starters, shared platform modules. For ordinary application wiring where you're choosing among intentional alternatives, stick with `@Primary` + `@Qualifier`.

  • If a type has two @Fallback beans and no regular bean, how is injection resolved?
    The fallbacks are the only candidates, so normal disambiguation runs among them: @Primary, then @Priority, then bean-name matching. If none resolves it uniquely, NoUniqueBeanDefinitionException is thrown.
  • How does @Fallback compare to @ConditionalOnMissingBean?
    @ConditionalOnMissingBean prevents the default bean from being created at all when another exists (a Boot config-time condition). @Fallback still creates the bean but deprioritizes it at autowiring time. @Fallback is core-container and simpler; @ConditionalOnMissingBean is Boot-specific and affects bean existence, not just selection.

saying these in an interview costs you the question

  • Confusing @Fallback with @Primary (getting the direction backwards)
  • Claiming @Fallback existed before Spring 6.2
  • Thinking @Fallback prevents the bean from being created (it only deprioritizes selection)

context