GraphQL for server-side resource aggregation
Tags: graphql, microservices, apigateway, bff
Published: 2020-03-12 19:44:40

---
title: GraphQL for server-side resource aggregation
published: true
description: In this post, I will explain how GraphQL can help with composing data coming from several services
tags: graphql,microservices,apigateway,bff
---

When implementing service oriented and microservices architectures, sooner or later, the aggregation of data coming from different services becomes a problem to face. In this post, we will see how GraphQL can help with this.

(A basic knowledge of GraphQL is required. You can learn GraphQL basics on the [official website](https://graphql.org/learn/)).

We are developing a property rental API, and the consumer needs an endpoint to fetch information about a property and its landlord. An example response would look like this:

```
GET /properties/1234

{
    id: 1234,
    address: "10 Downing Street",
    area: 90,
    landlord: {
        id: 882,
        name: "John Doe"
        email: "john.doe@mail.com"
    }
}
```

We can see two [aggregates](https://martinfowler.com/bliki/DDD_Aggregate.html) involved in this piece of information: _Property_ and _Landlord_.

In a monolithic application, we would write a query, with some SQL `JOIN` maybe, to fetch the data from a database, and marshall it to the above _JSON_.

However, let's assume in our rental organization we have a microservices architecture; we have a _Property Microservice_ and _Landlord Microservice_, [with a database for each one](https://microservices.io/patterns/data/database-per-service.html). For that reason, we can't just `JOIN` two database tables; integration between services is made across the network and not through database sharing.

We need an [API Gateway](https://hvalls.dev/posts/microservice-pattern-api-gateway) or [BFF](https://samnewman.io/patterns/architectural/bff/) to aggregate data from both services and serve it to the API consumer.

We could perform aggregation "by hand":

```kotlin
//This code belongs to API Gateway / BFF
fun getProperty(id: Int) : JsonObject {
    val property = propertyService.getById(id)
    val landlord = landlordService.getById(property.landlordId)
    return buildJson(property, landlord)
}
```

Note that `property` object, fetched from `propertyService::getById`, does not contain information about its `landlord`, but only its identifier; `landlordId`. We use that field to fetch the whole landlord info, through `landlordService`, and construct the full response `JsonObject`.

When implementing this approach, due to its stream-based nature, reactive programming tools like ReactiveX are quite useful.

An alternative to this, is letting GraphQL engine do the job.

### Resource aggregation using GraphQL

First, we are going to define the GraphQL schema:

```graphql
type Query {
  getProperty(id: String!): Property
}

type Property {
  id: String
  address: String
  area: Int
  landlord: Landlord
}

type Landlord {
  id: String
  name: String
  email: String
}
```

Now, we have to define a data fetcher for `getProperty` operation:

```kotlin
fun getPropertyDataFetcher() : DataFetcher {
  return DataFetcher { env -> {
     val propertyId = env.getArgument("id")
     return propertyService.getProperty(propertyId)
  }
}
```

So far, we have the information about the property. Now, we need to implement the data fetcher for its landlord:

```kotlin
fun getLandlordDataFetcher() : DataFetcher {
  return DataFetcher { env -> {
     val property = env.getSource<Property>()
     val landlordId = property.landlordId
     return landlordService.getLandlord(landlordId)
  }
}
```

With the schema and the fetchers, we are ready to build our `GraphQL` instance and make the query:

```kotlin
val graphQL = buildGraphQLFromSchemaAndFetchers()
executeQuery(graphQL, """{ query:
  getProperty(id: 1234) {
    id
    address
    area
    landlord {
      id
      name
      email
    }
  }
}""")
```

With this approach, we delegate the logic of the data composition to GraphQL library implementation, this way being less error-prone than doing it manually.

It looks like a declarative way; you tell it how to fetch properties, and how to fetch landlords. Then, just ask for the data you need and data aggregation is managed by GraphQL.

---

Sometimes, we tend to think of GraphQL just as a type of HTTP API; an alternative to REST.
This is true, but using GraphQL does not mean starting a GraphQL server. You don't need to expose an API of this type at all, depending on the use case you are trying to solve.

In this example, I have shown how to use GraphQL as a query engine and data aggregator, but I haven't mentioned anything about GraphQL servers.

Let's consider this code, that could be written using some modern REST tool:

```kotlin
@GET
fun getProperty(@PathParam("id") id: String) : Property {
  val property = executeQuery(graphQL, """{ query:
    getProperty(id: $id) {
      id
      address
      area
      landlord {
        id
        name
        email
      }
    }
  }""")
  return property
}
```

This is a REST API resource, but, under-the-hood, a GraphQL engine is responsible for aggregation of data from several sources. **There is no need to run any GraphQL server**.

There are many reasons you may not want to expose a pure GraphQL API. e.g. hard integration with frontend or other services, maintain compatibility, lack of GraphQL knowledge amongst the developers, or even organizational convention. Anyway, you can take advantage of GraphQL power and use it as a query engine, like we have just seen above.

I hope you enjoyed the article!