You might not need… the repository pattern The article argues that the repository pattern is often misapplied in CRUD-heavy backend applications using TypeScript, Go, and Rust, where it typically becomes a worse interface over the database rather than hiding meaningful persistence complexity. The author notes that real-world implementations frequently devolve into bloated interfaces with transaction leaks, non-aggregate-scoped methods, and mixed command/query responsibilities, which violates the pattern's original Domain-Driven Design principles. The conclusion is that most developers in these languages do not actually need a strict repository pattern, and it is perfectly acceptable to omit it. This post is mostly about CRUD-heavy backend applications in TypeScript, Go, and Rust, especially ones using modern typed query builders or lightweight ORMs. I’m not arguing that repositories are useless. I’m arguing that unless a repository protects a real aggregate boundary or hides genuinely meaningful persistence complexity, it usually becomes a worse interface over your database. The repository pattern originates from Patterns of Enterprise Application Architecture https://martinfowler.com/books/eaa.html , with Domain-Driven Design and 'layered' i.e. hexagonal/clean/onion etc architecture expanding on it from there. There are legitimate reasons it gained in popularity: - It provides a clean way to separate IO from business logic. - Testing business logic becomes a lot easier/faster, since there's a clean seam to swap in a test-double and keep everything in-memory. - It theoretically makes it easier to switch out the backing store if you change database/provider. - It fits well into the OOP world of Java, C and friends, where ORMs map to entities. What is a repository? Let's define the strict, traditional version of a repository: - A repository operates on aggregate roots. These are the invariant boundaries of your domain model. In traditional DDD, only one aggregate should be committed per operation, with everything else becoming eventually consistent which helps to minimize locking . The C documentation suggests relaxing this https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation single-transaction-across-aggregates-versus-eventual-consistency-across-aggregates if strong consistency is important. - A repository returns aggregates, fully hydrated. Vernon is explicit on this: repositories are not Data-Access-Objects. He spends an entire section distinguishing them. A DAO is expressed in terms of database tables and provides CRUD over them, while a repository operates on aggregates. - Since a repository is theoretically persistence-ignorant, it should in no way orchestrate a 'unit of work', i.e. a transaction boundary. If you're following the one-aggregate-per-operation rule, this becomes a lot easier. If not, you probably need to cheat and pass an open transaction through ALS https://nodejs.org/api/async context.html or some kind of thread-local storage equivalent. Nest CLS https://docs.nestjs.com/recipes/async-local-storage is a great example of this working really well. If you're using Go, I guess you can pretend you're not funneling it through the ctx grab-bag on every method. - The querying interface depends on context. Evans permits dedicated query methods findCancelledOrders , and suggests specifications https://en.wikipedia.org/wiki/Specification pattern when things become unwieldy. Vernon's strictest version of a repository is just add , save , fromId , but this is only practical when splitting reads from writes CQRS . Vernon also distinguishes between persistence-style repositories where you have to explicitly 'save' or update objects and collection-oriented ones which auto-track dirty objects . In TS/Go/Rust you're probably implementing a persistence-style one. Repositories in the wild If you follow a strict domain model, and propagate changes to other aggregates through events, you can adhere to the above criteria. You're probably writing Java, C , or JS with Nest https://nestjs.com/ which really, really wants to be Java . Your repositories might look like this: interface SupplierRepository { save supplier: Supplier : Promise