skip to content

How do -pl, -am, -amd, and -rf control which modules the reactor builds, and when would you use each?

level: seniorimportance: should knowfreq 45%

answer

  1. -pl = project list
  2. -am = upstream (also-make)
  3. -amd = downstream (dependents)
  4. -rf = resume-from after failure
  5. subset still topologically ordered

basics

~10 s

-pl picks specific modules (project-list). -am also builds their upstream dependencies (also-make). -amd also builds downstream dependents (also-make-dependents). -rf resumes from a given module (resume-from) after a failure.

solid answer

~40 s

These flags let you build a subset of the reactor instead of everything, which saves time on large multi-module projects. `-pl` (`--projects`) takes a comma-separated list of modules to build. `-am` (`--also-make`) adds the upstream modules those need, so their dependencies resolve from the reactor. `-amd` (`--also-make-dependents`) adds the downstream modules that depend on the selected ones — useful to verify you didn't break consumers after changing a shared module. `-rf` (`--resume-from`) restarts a failed full build at a specific module, skipping the already-successful earlier ones; Maven even prints the exact `-rf` command to use after a failure. All of these still respect topological ordering within whatever subset is selected.

code

bash · 3 lines
bash
mvn -pl core -am install      # core + its upstream deps
mvn -pl core -amd test        # core + everything depending on core
mvn install -rf :web          # resume a failed build at module 'web'

go deeper

for a junior

May know -pl selects modules; the rest is advanced.

for a middle

Can use -pl with -am to build a module and its dependencies.

for a senior

Distinguishes -am vs -amd by graph direction and uses -rf to recover from CI failures efficiently.

for a principal

Builds CI pipelines around change-based partial reactor builds (-amd for impact testing) and teaches the team the upstream/downstream model.

## Why partial builds exist A full reactor build of a large project can be slow. Maven offers flags to build a **subset** while keeping correct ordering and intra-reactor resolution. ## The flags - **`-pl` / `--projects <list>`** — build only the listed modules. You can identify a module by its `artifactId`, by its directory path (`:moduleA` by artifactId, or `path/to/module`), comma-separated. By itself, dependencies not in the list must already be installed in `~/.m2`. - **`-am` / `--also-make`** — with `-pl`, also build the **upstream** modules the selected ones depend on. This keeps those dependencies inside the reactor so they resolve from `target/` rather than `~/.m2`. Use it to build "this module and everything it needs." - **`-amd` / `--also-make-dependents`** — also build the **downstream** modules that depend on the selected ones. Use it to answer "if I change core, what breaks?" — it rebuilds/tests every consumer. - **`-rf` / `--resume-from <module>`** — restart a build at a specific module, skipping modules earlier in the order that already succeeded. After a failure, Maven prints `mvn <goals> -rf :failed-module` so you can resume without redoing successful work. ## Direction matters Think of the dependency graph as arrows pointing from consumer to dependency: - `-am` walks **toward dependencies** (upstream). - `-amd` walks **toward dependents** (downstream). ## Example ```bash # Build core and only what core needs: mvn -pl core -am install # Changed core? Rebuild + retest everything that uses core: mvn -pl core -amd test # Full build failed at module 'web'? Resume there: mvn install -rf :web ``` ## Caveats - `-pl` without `-am` requires upstream artifacts to be in `~/.m2`, or the build fails to resolve them. - Ordering inside the chosen subset is still topological. - `-rf` only makes sense in the context of a previously-attempted full ordering; module names use the `:artifactId` form or the path.

  • You changed a shared library module — which flag verifies nothing downstream broke?
    -amd (also-make-dependents), e.g. `mvn -pl shared -amd test`, which rebuilds and tests every module that depends on shared.
  • Why might `mvn -pl app install` fail while `mvn -pl app -am install` succeeds?
    Without -am, app's upstream reactor deps aren't built and aren't in ~/.m2, so resolution fails. -am adds them to the reactor.

saying these in an interview costs you the question

  • Swapping the meaning of -am and -amd
  • Thinking -pl alone always resolves reactor dependencies
  • Believing -rf reruns the whole build from scratch

context