GraphQL and DDD: the Missing Link

January 4, 2017

Photo of a foundation

When most people talk about GraphQL, they cite advantages in performance, predictable response format, type system, and versioning. All of these are awesome features, but I'd like to highlight another area where GraphQL shines: domain modeling.

Domain models capture concepts and processes for a specific business domain (ex: air travel, social networks, banking). Most business domains have complex rules, nuances, and requirements, even if they may seem simple at first. For example, let's consider banking: What's so hard about tracking an account balance and a log of credits and debits? For one, what type of currency does the account contain? What is the jurisdiction the account falls under, and what tax laws apply? Does the account accrue interest? Is this a shared account? As domain models organically grow to solve new problems, they become increasingly fractured, imprecise, even self-contradicting.

In Domain Driven Design, author Eric Evans suggests one way to reign in this type of growing complexity: extreme discipline around the language used to describe the problem and its solution. Choose nouns and verbs to describe sets of related processes, problems, and solutions that are precise and consistent, forming an "Ubiquitous Language" that developers, users, and domain experts can all use to mean the same thing. Evans goes further: the implementation should be an expression of the Ubiquitous Language, ideally taking on a form where it is self-documenting and sensible to a non-technical domain expert.

Object-oriented programming languages excel at expressing the core concepts of DDD: Entities and their relationships to one another, but the Ubiquitous Language tends to fall apart at the API, where it is arguably even more important. Consider the REST architectural style. By applying REST's Uniform Interface constraint (specifically its most opinionated requirement: Hypermedia as the Engine of Application State), you may inadvertently reduce the ability to express your domain model fluently. Other API technologies like SOAP XML-RPC keep the domain model intact, but at the cost of significant complexity and limited portability.

I believe GraphQL occupies a sweet spot — it concisely expresses the domain model's graph of relationships without leaking implementation details while remaining simple enough to share across different types and versions of clients. As in other schema-driven API technologies, the GraphQL schema can be seen as an expression of the Ubiquitous Language. For example, consider the requirement: "Groups have a collection of admins”. In code, this might look like

const groupId = 1234;
const admins = getGroupById(groupId).getAdmins();

In a GraphQL query:

{
  group(id: 1234) {
    admins { id }
  }
}

Notice how the linguistic expression "Groups have a collection of admins” is clear and intact in both cases, thanks to the GraphQL type system. By contrast, a REST API might have:

HTTP GET http://api.com/group/1234
...
{
  "id": 1234,
  "admins”: {
    "href”: "http://api.com/group/1234/admins”
  }
}

But we've lost something. What is the type/shape of the resource specified by the group/admins href? The linguistic description of the REST API has mutated from what we intended to convey. It now only expresses, "Groups have a related resource: admins”, and implies that you're on your own to figure out the rest (hopefully good documentation exists). I believe these kinds of client-driven data fetching use cases do not align with the strengths of REST as an architectural style.

Domain Driven Design stresses that a great Ubiquitous Language doesn't come for free. Engineers and domain experts will need to work together closely to evolve the Ubiquitous Language to accommodate new and changing requirements. To make this work with a GraphQL API, consider having non-technical people review proposed changes to the schema (ideally they can play around with the changes in GraphiQL). They should be able to give useful feedback about whether a type, relationship, or field is compatible with their interpretation of the domain model. Expect lots of debates about what to name things. If you give this a try, please drop me a line, I'd love to hear what you learn!