skip to content

Explain the deterministic ordering algorithm Spring Boot uses for auto-configurations, including the alphabetical fallback and cycle handling.

level: principalimportance: nice to knowfreq 18%

answer

  1. Three passes: alphabetical -> order -> before/after topological
  2. Alphabetical = determinism seed, not semantic
  3. Topological pass last => relationships win
  4. Cycle => IllegalStateException at startup
  5. Unknown before/after target => silently no-op

basics

~10 s

AutoConfigurationSorter first sorts classes alphabetically by name for a stable baseline, then re-sorts by @AutoConfigureOrder, then topologically applies @AutoConfigureBefore/@AutoConfigureAfter. Alphabetical is only a fallback; a cycle in before/after throws an error.

solid answer

~40 s

Spring Boot's AutoConfigurationSorter guarantees a deterministic order in three passes. First it sorts the candidate classes alphabetically by fully-qualified name — this makes the result independent of classpath/discovery order. Second it re-sorts by @AutoConfigureOrder value (lower = earlier, default 0). Third it performs a topological sort over the @AutoConfigureBefore/@AutoConfigureAfter constraint graph, treating each before/after as a directed edge; classes are emitted respecting all edges while preserving the prior stable order for anything unconstrained. Because the topological pass is last, explicit before/after relationships take precedence over order values. If the before/after edges form a cycle, the sorter cannot produce a valid order and throws an IllegalStateException naming the cycle. The alphabetical step is purely a fallback for otherwise-unordered pairs — you should never depend on class names to imply intended ordering.

code

java · 14 lines
java
// A cycle like this fails startup with IllegalStateException naming A and B:
@AutoConfiguration(before = B.class)
class A { }

@AutoConfiguration(before = A.class)   // A before B AND B before A => cycle
class B { }

// Correct, acyclic chain -- deterministic emission A, then B, then C:
@AutoConfiguration
class A2 { }
@AutoConfiguration(after = A2.class)
class B2 { }
@AutoConfiguration(after = B2.class)
class C2 { }

go deeper

for a junior

Not expected to know the algorithm.

for a middle

Should know alphabetical is a deterministic fallback, not the main rule.

for a senior

Should describe the three passes and that before/after wins over order.

for a principal

Should reason about cycle failures, silent no-op targets, stability guarantees, and diagnosing starter ordering bugs at scale.

**Goal: reproducible ordering.** Auto-configuration back-off (`@ConditionalOnMissingBean` etc.) is order-sensitive, so Spring Boot must order auto-config classes the *same way every run*, regardless of JAR scan order, filesystem order, or JVM. `AutoConfigurationSorter` provides that. **The three-stage pipeline.** 1. **Alphabetical baseline.** All candidate class names are sorted alphabetically by their fully-qualified name. This is the deterministic seed — 'unconstrained' pairs will fall back to this stable order. It is *not* a semantic ordering you should rely on; it just removes nondeterminism. 2. **`@AutoConfigureOrder` pass.** The list is re-sorted (stably) by each class's order value, `Ordered`-style: lower value first, default `0`. This is a coarse priority applied on top of the alphabetical seed. 3. **Topological before/after pass.** Each `@AutoConfigureBefore`/`@AutoConfigureAfter` (and the `@AutoConfiguration` `before`/`after` attributes) becomes a directed edge in a graph. The sorter walks this graph (a depth-first topological sort) emitting a class only after all classes it must come after have been emitted, and vice-versa for before. Where constraints leave classes free, it preserves the order from stages 1–2 (stable). Because this pass is applied last, a before/after constraint effectively overrides an order value that would place a class differently. **Cycle handling.** If the before/after edges contain a cycle (A before B, B before A, possibly transitively), no valid linear order exists. The sorter detects this during the topological traversal and throws an `IllegalStateException` describing the cycle (the offending classes). This is a startup failure — you must break the cycle by removing or correcting one of the constraints. **Subtleties and gotchas.** - **Missing/unknown targets are ignored.** A `before`/`after` referencing a class that is not among the candidate auto-configurations simply contributes no edge — no error, but also no effect. This is a common 'my ordering did nothing' cause. - **Order value vs relationship precedence.** Since before/after is applied last, if you set both and they disagree, the relationship wins; the order value can appear ignored. - **Stability everywhere.** Every stage is a stable sort, so the alphabetical seed leaks through wherever higher-priority signals are silent — giving reproducibility. - **Only auto-config classes participate.** The sorter operates on the auto-configuration candidate list (from `AutoConfiguration.imports`/legacy `spring.factories`), so annotations on non-candidates never enter the graph. - **Exclusions/filtering happen around it.** Conditions and `spring.autoconfigure.exclude` remove candidates; the sorter orders whatever survives. **Why it matters at scale.** In a large app with many starters, subtle ordering bugs (a starter that must run after `DataSourceAutoConfiguration` but forgot the `after`) manifest as intermittently missing or duplicated beans. Understanding the three-pass model lets you diagnose these deterministically, and the debug report (`--debug` / `ConditionEvaluationReport`) plus knowing the sort order pinpoints why a bean did or didn't back off. **When to reason about it.** Authoring or debugging starters, resolving 'bean defined twice / not defined' issues, or reviewing a library that fights framework defaults.

  • What happens if @AutoConfigureAfter names a class that isn't an auto-configuration candidate?
    It contributes no edge and is silently ignored — no error, but no ordering effect. A frequent reason ordering appears not to work.
  • How does Spring guarantee the same order across machines and JVMs?
    The first sorter pass sorts candidates alphabetically by fully-qualified class name, giving a deterministic baseline independent of classpath/scan order; subsequent stable passes preserve it for unconstrained pairs.

saying these in an interview costs you the question

  • Claiming ordering is purely alphabetical (it is only the fallback baseline)
  • Saying a before/after cycle is silently resolved rather than failing startup
  • Assuming a before/after to a non-candidate class still takes effect

context