The generic repository had been sold internally as a productivity win, and for a while it was. One base interface with save, findById, findAll, delete, parameterized over any domain object, meant a new service could be wired up to persistence in an afternoon instead of a day. Every team adopted it and nobody had to write the same boilerplate CRUD logic twice, and for the first year, that felt like exactly the kind of reuse the architecture was supposed to reward.
The cracks showed up gradually, in the shape of business rules that didn't fit the generic contract and ended up scattered around it instead. A cancellation didn't just need save, it needed to check three preconditions, emit a domain event, and update two related domain objects atomically. That logic didn't belong in a generic repository, so it got bolted onto the service layer as a special case, then another special case for refunds, then another for partial fulfillment, each one technically using the generic repository underneath while wrapping it in enough surrounding logic that the "generic" part stopped being where the real complexity lived. The repository stayed clean. Everything around it didn't.
The actual cost showed up during a sprint meant to add a straightforward feature: partial refunds needed to trigger a different notification path than full refunds. Finding where refund logic actually lived took most of the first two days, because it wasn't in one place, it was distributed across four service classes, each calling the same generic save method with different surrounding conditionals that had accumulated independently over a year of separate contributors solving separate tickets. There was no single use case class to open and read top to bottom. There was a repository interface that told you nothing about what a refund actually was as an operation.
We spent the rest of that sprint doing something other than the feature: extracting explicit use case classes, ProcessFullRefund, ProcessPartialRefund, each owning its own preconditions and side effects, with the generic repository pushed back down to where it belonged, a plain persistence detail behind the use case instead of the abstraction the business logic organized itself around. The feature that started the sprint shipped in the following one, in a day, because by then there was finally a single class whose job was to answer the question "what does a partial refund actually do." Finding the same logic afterward meant opening one class and reading it top to bottom, about half an hour.
A generic CRUD repository isn't wrong for what it actually is, a persistence detail. It becomes expensive the moment a team starts treating "wire it to the generic repository" as equivalent to "the business logic is handled," because those are not the same claim, and the gap between them doesn't show up on a velocity chart until the day someone needs to change behavior that was never given a home of its own.
More like this? I write short production war stories like this one, plus a deep-dive architecture series. Subscribe here if you want both in your inbox.
Recommended Resources for Java & Spring Boot Engineers
Disclosure: the links below are affiliate links from the Javarevisited publication. If you buy through them, I may earn a commission at no extra cost to you.
If you are preparing for Senior/Lead Java interviews or looking to solidify your Spring Boot & Architecture skills, check out these highly-rated resources from the Javarevisited publication. The 20% discount is applied automatically at checkout through these links; if it doesn't show up, use promo code friends20:
- Grokking the Java Interview Prepare for core Java, concurrency, JVM internals, and design pattern questions. Get Full Book (Paid) | Download Free Sample Copy
- Grokking the Spring Boot Interview Master Spring Core, Auto-configuration, Spring Data JPA, Security, and Microservices. Get Full Book (Paid) | Download Free Sample Copy
- Grokking the SQL Interview Deep-dive into query optimization, indexing, joins, and complex SQL window functions. Get Full Book (Paid) | Download Free Sample Copy
- The Complete Java + Spring + SQL Interview Bundle Get all three interview guides in a single heavily discounted package. Get the Ultimate Interview Bundle
- Spring Professional Certification Practice Questions (250+ Questions) Validating your skills? Practice with real exam-style questions before taking the Spring Professional certification. Get the Spring Professional Questions | Download Free Sample Copy


Top comments (0)