Introduction – When “Unnecessary” Dependencies Aren’t So Unnecessary
As architects, we often encourage teams to minimize dependencies. But in the world of Spring Boot, removing a “starter” dependency can silently dismantle multiple layers of auto-configuration that keep the system working seamlessly.
Recently, a developer removed the spring-boot-starter-data-jpa dependency from a microservice, thinking, “We’re not using Hibernate directly – why keep it?”
The application compiled, started fine, and then… strange things began to happen. Repositories failed to initialize, @Transactional annotations no longer behaved as expected, and entity operations started throwing exceptions.
In this post, we’ll look closely at what spring-boot-starter-data-jpa actually provides, what breaks when you remove it, and how this affects consistency across your microservices.
1. What spring-boot-starter-data-jpa Really Does
When you include:
you’re not just adding JPA. You’re pulling in a collection of integrated dependencies that Spring Boot uses to wire up persistence, transactions, and repositories automatically.
Specifically, it includes:
-
spring-data-jpa(Spring Data repository abstraction) -
hibernate-core(JPA implementation) -
jakarta.persistence-api(JPA specification) -
spring-tx(transaction management) -
spring-orm(integration between Spring and ORM frameworks) -
HikariCP (connection pooling, from
spring-boot-starter-jdbc)
Spring Boot then automatically configures:
-
The EntityManagerFactory
-
The PlatformTransactionManager (typically
JpaTransactionManager) -
The JPA vendor adapter (e.g., Hibernate)
-
Repository scanning and instantiation (
@EnableJpaRepositories)
So, this single dependency activates the entire ORM and transactional ecosystem.
2. What Happens When You Remove It
When you remove spring-boot-starter-data-jpa, the application doesn’t immediately crash – but several key layers quietly vanish.
a. Entity Annotations Stop Working
Classes annotated with @Entity, @Table, or @Id won’t be recognized because there’s no JPA provider (jakarta.persistence) or implementation (hibernate-core) on the classpath.
The project might still compile if the annotations are available from another dependency, but they’ll have no effect at runtime.
b. Repositories Fail to Initialize
If you have:
Spring Boot can’t create a bean for it. During startup, you’ll see:
because Spring Data JPA is no longer available to generate the repository proxies.
c. Transactions Stop Being Managed
Without JPA or ORM integration, Spring Boot can’t create a JpaTransactionManager.
Even if you annotate methods with @Transactional, Spring doesn’t know which transaction manager to use:
This breaks rollback behavior and atomic commits, which can lead to partial data writes.
d. Hibernate ORM is Gone
Spring Boot loses its ability to translate entity operations into SQL.
No more auto-DDL, dialect detection, or entity lifecycle management.
You’ll need to manually write all SQL and handle entity persistence yourself.
e. You Fall Back to Raw JDBC
You’ll still have HikariCP and a working DataSource from spring-boot-starter-jdbc.
So you can use:
and manually execute SQL statements:
This works — but you lose everything JPA and Spring Data were handling automatically:
mapping, cascading, relationships, caching, and entity synchronization.
3. What You Lose – The Hidden Chain Reaction
Removing spring-boot-starter-data-jpa doesn’t just affect persistence; it breaks the chain of consistency Spring Boot creates between layers.
| Layer | With JPA Starter | Without It |
|---|---|---|
| Entity Mapping | Automatically handled via JPA annotations | No ORM; manual SQL only |
| Repository Layer | Auto-generated proxies (JpaRepository) |
Not available |
| Transaction Management | Auto-configured via JpaTransactionManager |
Must configure manually |
| Hibernate ORM | Enabled and integrated | Missing |
| Schema Management | Controlled by spring.jpa.hibernate.ddl-auto |
Ignored |
| Connection Pool | HikariCP | Still available (from JDBC starter) |
From an architectural standpoint, you’ve moved from a declarative, transaction-managed system to a manual persistence model.
4. What Still Works
You can still use:
-
JdbcTemplateorNamedParameterJdbcTemplate -
A custom
DataSourceTransactionManagerfor manual transaction control -
Other persistence frameworks like MyBatis or jOOQ
But you’ll be responsible for:
-
Managing transactions explicitly
-
Writing and maintaining SQL
-
Handling object mapping manually
-
Ensuring rollback safety across methods
For small services, this might be fine. For larger ecosystems, it creates fragmentation and inconsistency in how persistence is managed.
5. Why This Matters for Microservice Consistency
In a distributed microservice landscape, consistency is not only about data but also about patterns.
If one team uses JPA and another uses manual JDBC, you’ve introduced subtle behavioral differences:
-
Rollback logic may behave differently
-
Error handling patterns diverge
-
Observability and tracing around persistence become inconsistent
-
Developers lose a shared abstraction layer
Uniformity in persistence handling ensures predictability – the cornerstone of maintainable microservice architectures.
6. Architect’s Insight
As architects, our job isn’t to mandate tools – it’s to ensure consistency in how services manage persistence.
A seemingly minor change, like removing a starter dependency, can undermine the very mechanisms that guarantee reliability and rollback integrity across services.
When you understand the value of what Spring Boot auto-configures, you can make conscious design decisions – instead of accidental regressions.
Consistency Principle
Every microservice should share a consistent persistence strategy. Removing key auto-configuration layers like JPA may simplify one service but silently introduce inconsistency across the ecosystem.