Thái Anh Đức

September 5, 2026

GraphQL design

GraphQL is a protocol. In the Web API world, there are REST and GraphQL among others such as JSON API. It is a way of expressing resources and capacities to consumers.

Hot Chocolate is a framework (library) that implements GraphQL for .NET. It is a great one. I like its design and easy of use. Fantastic framework for .NET.

EFCore is ORM framework that helps dealing with databases, such as SQL Server and PostgreSQL.

If you have a database with tables and columns, ask AI Agent, such as Claude Code, to generate a full GraphQL API with HotChocolate + EFCore. It will work immediately out of the box. Elegant, simple and fast!

It is a well-known pattern and a solved problem in AI era.

Ok. Now, let's dig into a more complicated scenario. The promise of GraphQL is that capacities is exposed from data model. The data storage (ex: database) is out of question.

Until, it is.

We have a situation the data comes from different sources. The main entities in the data model are not always coming from the database that the API owns. They come from another REST API.

Imagine a setup as below (it is a terrible example anyway)
image.png

And the "Sales API" will manage the category for products and which shops have them. And we need to expose a GraphQL model
product {
     id
     name
     sku
     categories: [{}]
     availableShops: [{}]
}

The first three (id, name, sku) come from "Inventory API", the last two are extended from GraphQL interface.

It is pretty straightforward using "Extended Types" and "Data Loader" supported by Hot Chocolate (Google them or ask Claude Code for more information). It is a solved problem and most plumping work can be done by Claude Code.

Run the solution and soon you will get an exception from EFCore saying that "the DbContext is called from two different threads." The detail message does not matter here. By design, EFCore does not allow to use a DbContext instance in parallel. It is a reasonable design choice.

Back to Claude Code, if you push hard enough, it will show you 4 solutions. All are trying to avoid the DbContext thread-safe issue by using DbContextFactory. The idea is to create a new DbContext instance for each data loader instance. It works but terribly dangerous. WHY?

It changes from having only ONE DbContext instance per request to AS MANY AS requested DbContext instances. The connections to the database is out of control; not mentioned the data consistency. Once the door is open, you cannot stop devils doing evil things.

AI with its all mighty power can do everything and anything regardless of consequences. I do not think it knows or cares as long as the mission accomplished.

What is the alternative? Redesign the data model. I want to ensure that there is only one DbContext instance per request. Because we have two extended properties on the model, there are two data loaders. Basically, one extended property has one data loader. If we merge them into ONE bigger construct, a single class, then there is only ONE data loader. It is not a universal solution; it is an alternative with trade-offs.

The GraphQL contract looks like
product {
     id
     name
     sku
     extensions {
         categories: [{}]
         availableShops: [{}]
     }
}

All extended properties that are loaded from the database lives under "Extensions" class.

It works beautifully for our scenario. We are aware of the trade-offs and we have ideas to solve them if they become an issue. I doubt it will be.

It is an interesting case. When I asked Claude Code for solutions, it gave me the solution that looked correct but error-prone in race condition. Report the issue, it gave another solution to solve that race condition with a full explanation. They all looked legit with a big potential dangerous impact. Asked it to redesign the model, it gave nothing except circling back to one of previous solutions.

Human brain is still required.

About Thái Anh Đức

Software architect from Việt Nam. Partner at https://ritvn.com/.  Train with Kettlebells. Run with minimal shoes and sandals.