Choosing a GraphQL server library in Go

In this short article, I compare various Go libraries to build a GraphQL server by mainly reading the documentation and some of source code. Please note that this is my personal opinion at the time of writing which may or may not be changed over time.

Background

Apollo Client is one of my favorite libraries recently to create React apps. React Apollo allows us to develop an app handy with GraphQL. As a GraphQL server, Apollo Server is a good option in this ecosystem, or if you want it without coding, BaaS such as AppSync and Prisma should be a good option too. Nevertheless, for some reason, I try to use Go for a GraphQL server, and I look for libraries to help developing a GraphQL server.

Candidates

  1. https://github.com/graphql-go/graphql
  2. https://github.com/graph-gophers/graphql-go
  3. https://github.com/samsarahq/thunder
  4. https://github.com/playlyfe/go-graphql
  5. https://github.com/vektah/gqlgen

Comments on each library

The first one is probably the oldest one. It says:

Follows the official reference implementation graphql-js.

The resolver example in README is:

Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return "world", nil
},

This looks like dynamic typing and it might not fit well with static typing in Go. There’s a third-party library graphql-go-handler, which supports GraphiQL and Playground.


The second one seems getting attention recently. The resolver is written as a method like:

func (_ *query) Hello() string { return "Hello, world!" }

This looks familiar. Although GraphiQL is not included, which I agree is a good decision, the example code shows how easy it is.

The names of the struct fields have to be exported and have to match the names of the GraphQL arguments in a non-case-sensitive way.

One thing I concern is this case insensitivity, which is not very intuitive at least to me.


The third is an exiting one.

Thunder generates resolvers automatically from Go struct types and function definitions.

This sounds very promising.

object.FieldFunc("posts", func() []post {
return posts
})

This is a resolver, which looks straightforward.

If you’re adventurous, please give it a try.

Besides its immaturity, my concern could be this reflection-based approach is slightly apart from Apollo Server in my mind. Maybe, just a trade-off.


The forth one says:

Its aim is to be the fastest GraphQL implementation.

This should be one of good properties.

resolvers := map[string]interface{}{}
resolvers["QueryRoot/pets"] = func(params *graphql.ResolveParams) (interface{}, error) {
return []map[string]interface{}{
{
"__typename": "Dog",
"name": "Odie",
"woofs": true,
},
}, nil
}

This doesn’t look very appealing. In addition, unfortunately, the project is not active recently while having some missing functionality still to be implemented.


The fifth one is a bit different because it’s a generator.

gqlgen is golang library for building graphql servers without any fuss.

It generates template code from a schema definition and all you need is to write resolvers.

func (a *MyApp) Query_todos(ctx context.Context) ([]Todo, error) {
return a.todos, nil
}

This is a resolver, which makes sense. I’m not used to such generators and personally hesitates writing configurations in YAML, but I’m pretty sure this may work well for certain people.

Conclusion at this point

After looking through 5 candidates above, two possibilities for me are graph-gophers’ graphql-go and samsarahq’s thunder. I pretty much like the thunder approach and I can imagine how easy it is to code a simple example. However, I can’t predict how well it goes in long-term period. The minimal API approach of graphql-go seems to last long. So, at this point, I choose graph-gophers’ graphql-go.