skip to content

spring-boot-starter-* aggregation

A starter like spring-boot-starter-web is an almost-empty artifact whose value is its curated, version-aligned transitive dependencies. Knowing there is no code in it is a small answer that shows you have actually looked.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is a Spring Boot starter, and what problem does it solve?

level: juniorimportance: must knowfreq 85%

answer

  1. One coordinate = curated jar set
  2. Empty POM, no code
  3. starter-web = MVC + Tomcat + Jackson
  4. Versions from spring-boot-dependencies BOM
  5. Starter != auto-config

basics

~20 s

A starter is one dependency coordinate that pulls in a curated, version-aligned set of libraries for a feature. Example: spring-boot-starter-web adds Spring MVC, embedded Tomcat, and Jackson together, so you declare one line instead of hand-picking and version-matching many jars.

solid answer

~40 s

A Spring Boot starter is a convenience dependency descriptor: a jar that is mostly an empty POM whose only job is to declare a coherent, transitively-resolved set of libraries for a use case. spring-boot-starter-web brings spring-webmvc, spring-web, the JSON starter (Jackson), and embedded Tomcat; spring-boot-starter-data-jpa brings Hibernate, spring-data-jpa, spring-jdbc and HikariCP; spring-boot-starter-security brings Spring Security. Starters solve two problems: (1) you no longer manually list a dozen coordinates, and (2) you don't manage versions yourself — the versions come from Spring Boot's managed dependency BOM (spring-boot-dependencies), so the whole stack is mutually compatible. Starters also commonly trigger matching auto-configuration on the classpath. Official ones are named spring-boot-starter-*; third-party ones follow name-spring-boot-starter.

code

kotlin · 11 lines
kotlin
// build.gradle.kts — one line each, no versions needed
dependencies {
    // Pulls spring-webmvc, spring-web, Jackson, embedded Tomcat
    implementation("org.springframework.boot:spring-boot-starter-web")
    // Pulls Hibernate, spring-data-jpa, spring-jdbc, HikariCP
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    // Pulls spring-security-web + spring-security-config
    implementation("org.springframework.boot:spring-boot-starter-security")
}
// The Spring Boot Gradle plugin imports the spring-boot-dependencies BOM,
// so all transitive versions are aligned automatically.

go deeper

for a junior

Know that one starter coordinate replaces many hand-picked jars and that starter-web brings MVC + Tomcat + Jackson.

for a middle

Explain that starters carry no code, list what starter-web/data-jpa actually pull, and that versions come from a BOM.

for a senior

Distinguish starter (dependency bundle) from auto-configuration, and describe the version-alignment guarantee across multiple starters.

for a principal

Frame starters as a curated-dependency contract enabling org-wide reproducible builds; reason about BOM governance and prefix conventions.

## The problem starters solve Before starters, adding a web layer meant hand-listing spring-webmvc, spring-web, a servlet container, a JSON library, validation, logging — and getting all their versions mutually compatible. That is tedious and error-prone (a Jackson version that doesn't match spring-web, a Hibernate that doesn't match spring-data-jpa, etc.). ## What a starter actually is A **starter** is a Maven/Gradle module that is (almost) an **empty jar** — it contains **no code**, only a `pom.xml` (its dependency metadata). Its transitive dependencies are the curated set. When you add `org.springframework.boot:spring-boot-starter-web`, Maven/Gradle transitively resolves everything it declares. Example transitive closure of **spring-boot-starter-web**: - `spring-boot-starter` (the core starter: auto-config, logging, `spring-core`, YAML) - `spring-boot-starter-json` (Jackson databind/core/annotations) - `spring-boot-starter-tomcat` (embedded Apache Tomcat) - `spring-web` and `spring-webmvc` **spring-boot-starter-data-jpa** pulls: `spring-boot-starter`, `spring-boot-starter-jdbc` (which brings **HikariCP** connection pool + `spring-jdbc`), `hibernate-core`, `spring-data-jpa`, `spring-orm`, and the Jakarta Persistence API. **spring-boot-starter-security** pulls: `spring-security-web`, `spring-security-config`, and `spring-boot-starter`. ## Version alignment (the other half) Starters themselves usually **do not pin versions** of the libraries they pull. Versions come from the **`spring-boot-dependencies` BOM** (a `<dependencyManagement>` bill-of-materials), which you inherit either via the `spring-boot-starter-parent` parent POM or by importing the BOM. So `spring-boot-starter-web` + `spring-boot-starter-data-jpa` are guaranteed to agree on the shared `spring-core`/Jackson versions. ## Starters vs auto-configuration (don't conflate) A starter is a **dependency bundle**. **Auto-configuration** is the separate mechanism (in `spring-boot-autoconfigure`) that inspects the classpath and wires beans. They pair well — putting Tomcat + Spring MVC on the classpath causes web auto-config to fire — but they are distinct: you could add the same jars manually and auto-config would still trigger. ## Naming convention - Official starters: `spring-boot-starter-*` (prefix). Anthropic-of-Spring reserves this prefix. - Third-party/custom: put your name first, `acme-spring-boot-starter`. ## When to use Always prefer the starter over hand-listing jars; only drop to individual coordinates when you must exclude/replace part of the curated set (e.g., swap Tomcat for Jetty).

  • Does adding a starter automatically configure beans?
    Not by itself — the starter only puts jars on the classpath. Auto-configuration (spring-boot-autoconfigure) reacts to those classpath contents and @ConditionalOn... to create beans. They're separate mechanisms that usually work together.
  • Why don't you specify a version for spring-boot-starter-web?
    Because the version is managed by the spring-boot-dependencies BOM, inherited through spring-boot-starter-parent or imported directly (or via the Gradle plugin). The BOM pins compatible versions for the whole stack.

saying these in an interview costs you the question

  • Thinking a starter contains the actual framework code (it's an empty POM/jar of dependencies)
  • Conflating starter (dependencies) with auto-configuration (bean wiring)
  • Believing you must specify versions for each transitive library

context

open as a page

How does Spring Boot keep all the libraries a starter pulls version-aligned? Explain the role of spring-boot-starter-parent vs importing the BOM.

level: middleimportance: must knowfreq 70%

basics

~20 s

Versions live in the spring-boot-dependencies BOM — a dependencyManagement list of managed versions. You inherit it either by using spring-boot-starter-parent as your Maven parent, or by importing spring-boot-dependencies directly (Gradle's Boot plugin does this for you). Starters then omit versions.

open as a page

spring-boot-starter-web ships embedded Tomcat. How would you switch the embedded server to Jetty (or Undertow) instead?

level: middleimportance: should knowfreq 45%

basics

~10 s

Exclude spring-boot-starter-tomcat from spring-boot-starter-web, then add spring-boot-starter-jetty (or spring-boot-starter-undertow). Auto-configuration detects Jetty on the classpath and starts it as the embedded server instead of Tomcat.

open as a page

How would you author your own reusable starter for an internal library, and what are the conventions?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Split it in two: an autoconfigure module with @AutoConfiguration classes (registered in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports), and a thin starter module that just depends on the autoconfigure module plus required libraries. Name it acme-spring-boot-starter (name first, not the reserved spring-boot-starter- prefix).

open as a page

At org scale, curated starters can pull large transitive graphs (bloat, unwanted CVE-carrying jars, duplicate logging bindings). How do you keep dependency hygiene while still benefiting from starters?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Keep the version alignment from the BOM but prune what you don't use: exclude unwanted transitive jars (e.g. resolve duplicate logging bindings), audit the resolved graph with dependency:tree / dependencies, enforce via a shared internal BOM/platform, and let auto-config back off for absent classes so unused starters aren't force-added.

open as a page