“Take only what you need, not what you want.”
― Forrest Carter
Introduction
In this first part of “How to Implement GraphQL in Microservices Using Node.js” series, , I will share about creating a GraphQL server which connects to the REST API service we created before. It also includes of what I think is a good structure to create a GraphQL Server which supports multiple features.
I will share the project through GitHub at the end of the post as usual.
Let’s get started.
What is GraphQL?
To quote from the official website of GraphQL:
GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data.
What is GraphQL?
Or, in simpler words I hope, you send a query to get the data you need from the provided data. Let’s say a row from database has 8 properties. With GraphQL, you can get from 1-8 properties from the data by requesting the property names you need in the query.
The result is you will get the data with only the properties you requested and the other not requested properties are ignored.
Why GraphQL?
GraphQL helps clients to fetch the right amount of data needed to render the view. Because it lets the client-side to define the response of a request, it’s also able to reduce the bandwidth needed on fetching the response.
Additionally, it removes the complexity of managing endpoints of a REST API. The usual practice is by creating a new HTTP endpoint (usually /graphql
) to fetch the required data.
Requirements
If you don’t have Node.js installed yet, here are some links for you:
- Node.js
I recommend download the LTS one. Because, well, longer term support. To make sure it works, typenode -v
on your Terminal after installation: - Postman or Insomnia
To check whether your API is working. Personally, I prefer Postman because of the multiple tabs. To know it’s working, well, just open the app.
Part 1 – Create GraphQL Server
Create a New Express Service
I will not go into details here. Please refer to this tutorial when creating a new service. Name the service as cli-nodejs-gql
. And by the time this tutorial is written, I use Node 12.
Install Required Libraries
After initiating the new project, install these libraries:
Hello World In The Style of GraphQL
Create a new file named index.js
, which contains this snippet:
// index.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`? Server ready at http://localhost:4000${server.graphqlPath}`)
);
The code will be explained on the next sections. Let’s make sure the configuration works for now.
Run the service with npm start
or node index.js
. It should look like this if it ran successfully:

Then, run the Postman app and access http://localhost:4000/graphql
. You can also access the GraphQL Playground by entering the URL to your web browser.
- If you prefer Postman, on the
body
sub-tab, pickGraphQL
, and navigate to thequery
window. - If you prefer the Playground, directly navigate to the left text area field.
Whichever you choose, write this query:
{
hello
}
And leave the GraphQL variables for now. Lastly, click Send
to get the results. If everything works well, it should be like this screenshot below:

Restructuring Hello World
The “Hello World” works, but I want to make the code easier to read and maintain. If I want to add a new module, I would not stack all the queries and mutations in index.js
, as it would make the file super long and difficult to trace.
Another reason is, I don’t want to make another refactoring post.
So, let’s create some new directories:
<project-root>/graphql
<project-root>/graphql/helloworld
<project-root>/graphql/helloworld/queries
Then, add some empty files:
<project-root>/graphql
:index.js
<project-root>/graphql/helloworld
:index.js
<project-root>/graphql/helloworld/queries
:index.js
resolvers.js
schemas.gql
Resolvers.js
Let’s start from moving the resolvers
part from <root>/index.js
to /graphql/helloworld/queriers/resolvers.js
. Add this part from index.js
without changing anything and and module.exports
at the end of the file:
// <project-root>/graphql/helloworld/queries/resolvers.js
const resolvers = {
Query: {
hello: () => 'Hello world!'
}
};
module.exports = resolvers;
Schemas.gql
Next, we will add schemas.gql
. In this file, we write the type definition and export it with module.exports
. See this snippet below:
// <project-root>/graphql/helloworld/queries/schemas.gql
module.exports = `
type Query {
hello: String
}
`;
/helloworld/queries/index.js
Then, we import both the resolvers
and schemas
modules into /helloworld/queries/index.js
:
// /helloworld/queries/index.js
const resolvers = require('./resolvers');
const schemas = require('./schemas.gql');
module.exports = {
resolvers,
schemas
};
/graphql/helloworld/index.js
Another index.js
file, but this one’s in the /graphql/helloworld
directory. This module imports all resolvers and schemas defined in queries
and (later on if needed) mutations
. After importing the modules, it merges them into one resolvers and schemas. See this snippet below:
// /graphql/helloworld/index.js
const queries = require('./queries');
// if the helloworld have mutations, add them here also.
// const mutations = require('./mutations');
module.exports = {
resolvers: {
...queries.resolvers
//...mutations.resolvers
},
schemas: [
queries.schemas,
// mutations.schemas
].reduce((acc, types) => { return acc + types })
};
/graphql/index.js
The next step is to import all features existing in the project. We do this in /graphql/index.js
. After importing, this module merges all resolvers and schemas already defined in each features before. The helloworld
is a feature and thus, we will import helloworld
to this file:
// /graphql/index.js
const { gql } = require('apollo-server-express');
const helloworld = require('./helloworld');
const typeDefs = gql`${[
helloworld.schemas,
// feature_a.schemas,
// feature_b.schemas,
// feature_c.schemas
].reduce((acc, types) => { return acc + types })}`;
const resolvers = {
...helloworld.resolvers,
// feature_a.resolvers,
// feature_b.resolvers,
// feature_c.resolvers
};
module.exports = {
typeDefs,
resolvers
};
Remember to import { gql }
from apollo-server-express
library to convert the type definition strings as GraphQL.
index.js
OK, this is the final index.js
. We will remove the typeDefs
and resolvers
from this file. And then, we will import the graphql
module and then initialize the ApolloServer
with it. See this snippet below:
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const graphql = require('./graphql')
const server = new ApolloServer(graphql);
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`? Server ready at http://localhost:4000${server.graphqlPath}`)
);
Much simpler now.
Test the code
Run npm start
and try to hit the endpoint localhost:4000/graphql
with the same configurations from the previous “Hello World” section. If everything goes well, it will give the same result.
Preparing To Support Many Features
We have pretty much refactor the code of “Hello World”, and we can already see the pattern of supporting multiple features. But, it’s not completed yet. Because, the entry point type Query
is still in helloworld’s schema and resolver.
We will move type Query
to a directory named _root
. So, whenever we need to add new features, we will register it here at first.
_root
Let’s create some new directories:
<project-root>/graphql/_root
<project-root>/graphql/_root/queries
Then, add some empty files:
<project-root>/graphql/_root
:index.js
<project-root>/graphql/_root/queries
:index.js
resolvers.js
schemas.gql
For every index.js
file, just copy them directly from the helloworld
‘s directories. It’s the same.
We will add some codes in _root/queries/schemas.gql
first:
module.exports = `
type Query {
helloworld: HelloWorld
}
schema {
query: Query
}
`;
Here is the “entry point”. It is important to first declare the type Query
, and add the schema
part. This way, the GraphQL server will know that what we will get from the top query is Query
. Next, add the property helloworld
inside type Query
, which will be obtained from type HelloWorld
.
Next, we modify _root/queries/resolvers.js
to resolve the requested query result:
// Provide resolver functions for your schema fields
const Query = {
helloworld: () => 'helloworld'
};
module.exports = { Query };
The resolver object must have the same as declared on schema. The property helloworld
must be a function or an object. In this case, I created a dummy function which returns string. But, isn’t helloworld
‘s type is HelloWorld
? Yes, we will declare HelloWorld
later in its own schema and resolver. Lastly, export Query
as a module inside a bracket as an object.
Then, on /graphql/index.js
, register _root
‘s schemas and resolvers:
const { gql } = require('apollo-server-express');
const root = require('./_root');
const helloworld = require('./helloworld');
const typeDefs = gql`${[
root.schemas,
helloworld.schemas,
].reduce((acc, schemas) => { return acc + schemas })}`;
const resolvers = {
...root.resolvers,
...helloworld.resolvers
};
module.exports = {
typeDefs,
resolvers
};
First, import _root
, then assign the root.schemas
to typeDefs
and the root.resolvers
to resolvers
.
Modify HelloWorld, again.
Yes, I know it’s the third time. I promise it’s the last time. Let’s make it quick then.
First, we modify helloworld/queries/schemas.gql
:
module.exports = `
type HelloWorld {
hello: String
world: String
}
`;
In this file, we create the type for HelloWorld
, the one we declared in Query
before. It has the property hello
and world
, both are strings.
So, what is inside hello
and world
? We will resolve it in the helloworld/queries/resolvers.js
file:
// Provide resolver functions for your schema fields
const HelloWorld = {
hello: () => 'Hello!',
world: () => 'World!'
};
module.exports = { HelloWorld };
Pretty similar to the _root
resolver, but in this file it means that whenever a HelloWorld
type is requested, it will return at least one of the properties hello
or world
. Then, we export the HelloWorld
to be registered in the GraphQL server.
Test the code
Run npm start
. And execute this query:
query {
helloworld {
hello
world
}
}
The result should be like in this screenshot if everything goes well:

Conclusion
Alright, it’s my favorite part of the post: the conclusion. So, at this point we should have learned about:
- Quick introduction of GraphQL.
- Setting up a GraphQL server.
- Refactor a GraphQL server code to support many services later on.
And as promised, you can get the source code in GitHub here.
Actually, I wanted to write about the queries and mutations also in this post. The post became so long that I decided to make another post about it.
I hope this will be a help for you to create a GraphQL server. Lastly, if I missed something, let me know in the comments!
Next post in the series:
Part 2 – GraphQL Queries
“You will never get everything in life but you will get enough.”
― Sanhita Baruah