Why not use database-driven design

Ürgo Ringo
Javarevisited
Published in
3 min readDec 18, 2023
One of the world’s first databases used in accounting ~3000 BC from Sumeria (source)

While most systems require some kind of database starting the design from the database schema is not a very good approach. It doesn’t give good guidance for arriving at an optimal system design. In addition, even though it puts the database front and center of the design process it’s not the most effective approach to building an optimal database schema either.

Feedback

The key ingredient with any design approach is getting early feedback. This is where the data-driven approach falls short.

It doesn’t matter if we use an entity-relationship diagram (ERD), a UML class diagram, or some custom data structure notation. All come down to using nouns from business requirements and representing these as concepts in the system. At best the noun approach works only on a very high level. The problem is that we cannot validate what data structure works best. Yes, we can follow the idea of data normalization but that is only a data storage optimisation technique.

The only way to validate data structure is by understanding what are the different operations we need to perform on that data. So it’s the behavior that we need to model first not the data. Data follows behavior, not the other way around.

In ERDs there is no place where to put the behavior — modeling behavior is not the purpose of this notation. It’s not much better with class diagrams either. We could depict the behavior as methods on classes but that still does not give feedback on which composition of classes is the most suitable one.

All of this becomes even more complex when we want to validate the applicability of different alternatives like event sourcing or separating data for query and modification as per CQRS. These are techniques that are driven by expected system behavior and then model data accordingly.

Complexity

The other principle of design is that we should use the most complex aspect to drive the design of the system. For a typical customer-facing system this means not starting from the backoffice but the main jobs that the customer wants the system to perform.

In most cases, the complexity lives in business logic (1). As this is the most complex part of the system, it’s logical that we don’t want to add any accidental complexity by making it any harder than necessary to operate on the persistent data.

Interfaces

What does starting from the behavior look like?

Once we have identified the main use cases the next step is looking at the interfaces. Typically there are two kinds of interfaces — UIs and APIs. Since UIs are generally built on top of APIs they give good guidance on how to optimise the APIs.

In the case of microservice architecture, APIs are also consumed by other services. To avoid creating accidental complexity in service-to-service collaboration it is critical to optimize the composition of services.

Start by figuring out what is the most convenient API that a given service should expose to others. To fully validate the API look at the composition of endpoints that are needed to fulfill each use case. It’s a good idea to not only look at the APIs the given service should have but also what APIs it needs to consume.

Database last

When should we start working on the database schema then?

I suggest building database schema iteratively instead of upfront and letting the business logic/domain model drive it.

With this approach, we will first do some upfront design of the API and analyze how it fits into the overall system context. Then iteratively tease out the domain model and, based on that in small iterative steps, build the most suitable database schema.

(1) Depending on the domain the complexity and competitive advantage can often live in the UI/frontend. For example, in e-commerce, there are lots of headless off-the-shelf solutions that make a big part of the backend application logic a commodity.

--

--

Ürgo Ringo
Javarevisited

Have been creating software for 20 years. Cofounded a software consultancy, worked as an IC and team lead at Wise. Currently working at Ibank.