skip to content

In a Maven multi-module build, what determines the order in which the reactor builds the modules?

level: juniorimportance: must knowfreq 70%

answer

  1. topological sort
  2. dependency edges not <modules> order
  3. parent + plugins count as edges
  4. cycle => build fails
  5. reactor summary shows order

basics

~20 s

Maven's reactor builds modules in dependency order, not in the order they are listed in <modules>. It looks at each module's <dependency> entries and builds a needed module before the one that depends on it.

solid answer

~40 s

The reactor (Maven's multi-module engine) computes a topological sort of the modules based on inter-module dependency edges. It scans every module's <dependency> declarations, plus parent/plugin references, finds which other reactor modules each one depends on, and orders the build so a dependency is always built before its consumer. The order in the aggregator POM's <modules> list is only a starting hint and a tiebreaker when modules are independent; it does NOT dictate build order. So if module-app depends on module-core, core builds first even if app is listed first. A cyclic dependency between modules makes the graph unsortable and Maven fails with a cycle error.

code

xml · 8 lines
xml
<project>
  <packaging>pom</packaging>
  <modules>
    <module>app</module>
    <module>core</module>
  </modules>
</project>
<!-- If app depends on core, Maven builds core BEFORE app -->

go deeper

for a junior

Knows the reactor builds dependencies before dependents and that <modules> order isn't authoritative.

for a middle

Can explain that edges come from <dependency>, <parent>, and plugins, and that the result is a topological sort.

for a senior

Understands tiebreaking by declaration order, cycle failures, and how missing declared edges cause subtle ordering bugs.

for a principal

Designs module graphs to stay acyclic and shallow, and treats explicit dependency declarations as the contract that keeps reactor ordering deterministic.

## What the reactor is The **reactor** is the part of Maven that handles a build spanning multiple modules. When you run `mvn` against an **aggregator POM** (a POM with `<packaging>pom</packaging>` and a `<modules>` block), Maven collects all listed modules into one build session, decides an order, and builds them in sequence. ## Build order = topological sort, not declaration order The single most important fact: **the order of `<module>` entries does NOT decide build order.** Maven builds a directed graph where an edge points from a module to each other reactor module it depends on, then performs a **topological sort** — every module is built only after all the modules it depends on are built. Maven derives the edges from: - `<dependency>` entries that reference another reactor module's GAV (groupId/artifactId/version) - The `<parent>` reference if the parent is also in the reactor - Plugins (and their dependencies) that are themselves reactor modules The `<modules>` list order is used only as a **stable tiebreaker** for modules that have no dependency relationship between them. ## Why this matters It means you can list modules in any convenient order (often alphabetical) and Maven still gets it right. It also means a missing `<dependency>` edge — e.g. relying on classpath leakage rather than a real declared dependency — can produce a wrong order or flaky builds. ## Cycles fail the build If module A depends on B and B depends on A (directly or transitively), the graph has a **cycle**, no valid topological order exists, and Maven aborts with an error like "The projects in the reactor contain a cyclic reference." ## Example ```xml <!-- aggregator pom.xml --> <project> <packaging>pom</packaging> <modules> <module>app</module> <!-- listed first --> <module>core</module> <!-- listed second --> </modules> </project> ``` If `app/pom.xml` declares a dependency on `core`, Maven still builds **core first, then app**, ignoring the listing order. ## Inspecting the order Run the build with `-X` (debug) or just read the reactor summary at the end of any multi-module build — Maven prints the modules in the exact order it built them.

  • If I reorder the <modules> list, will the build order change?
    No — declaration order only breaks ties between independent modules; real build order comes from the dependency graph.
  • What happens if two modules depend on each other?
    The graph has a cycle, no topological order exists, and Maven fails with a cyclic reference error. You must break the cycle, often by extracting shared code into a third module.

Like cooking a recipe: you don't chop onions in alphabetical order, you do prep steps in the order the later steps need them.

saying these in an interview costs you the question

  • Saying modules build in the order they appear in <modules>
  • Believing you must manually order modules so dependencies come first
  • Thinking parent POM references don't affect ordering

context