Before moving ahead, it makes sense that we understand that GraphQL itself is nothing but a specification – http://spec.graphql.org/draft/. One can implement the specification in any language of choice.
Architecture 1: Direct database access
In the first architectural pattern to implement GraphQL, we have a simple GraphQL server setup, which directly accesses the database and returns required data.
As we can see, this type of implementation is possible mostly for fresh development. When we make a decision while setting up the system that we want to support GraphQL based access, we build the system with first-hand support.
Architecture 2: Support for existing systems
More often, we come across scenarios where we will need to provide support for existing systems, which are usually built with support for REST and microservices-based access to existing data.
The pattern above indicates an additional layer between the actual backend implementation and the client. The client makes a call to the GraphQL server, which in turn connects to actual backend services and gets the required data.
Architecture 3: Hybrid Model
We have talked about 2 patterns so far, one where the GraphQL server has direct database access, and the second when the GraphQL server fetches data from an existing legacy system. There can be a use case where partial implementation is done fresh and some data is being fetched from existing APIs. In such a use case, one can implement a hybrid model.
The discussion about various types of GraphQL implementation is not completed without talking about Resolver functions. A resolver function is responsible for mapping the query with the implementation or actual fetching of data. So all the above-mentioned implementation will drill down to the fact that how the GraphQL resolver function is written to resolve the query and fetch the data.