# graphql-go/graphql: a schema-first GraphQL engine for Go servers

> graphql-go/graphql builds schemas in Go code and executes queries, mutations and subscriptions itself. It suits Go teams that want GraphQL without a code generator, and it is a poor fit for anyone expecting a batteries-included HTTP server.

**graphql-go/graphql** — An implementation of GraphQL for Go / Golang

- Repository: https://github.com/graphql-go/graphql
- Stars: 10,143 · Forks: 845
- Language: Go
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/graphql-go-graphql

## What graphql-go/graphql actually provides

This is a GraphQL engine, not a web framework. The README describes it as "An implementation of GraphQL in Go" that follows the official reference implementation graphql-js. That sentence sets the scope: the package parses a request string, validates it against a schema, executes it, and returns a result. Everything about transport, routing, middleware and authentication sits outside the module.

The audience follows from that. If you are writing a Go service and you want the schema defined in Go rather than in a separate SDL document, this library is aimed at you. The README's own example builds a schema from graphql.Fields and graphql.ObjectConfig values, so the type system is expressed as Go data structures. Teams that prefer schema-first workflows with a .graphql file and generated bindings will find the ergonomics inverted here.

The repository layout supports the description. The top level carries executor.go, definition.go, introspection.go, directives.go, rules.go and a language/ directory, which is the shape of a self-contained engine: a parser, a type definition layer, validation rules, introspection, and an executor. There is no server package in the listing, and the README does not claim one.

## How a request flows from string to JSON

The README example shows the whole pipeline in about ten lines. You construct a schema with graphql.NewSchema, wrap the incoming query in a graphql.Params value alongside that schema, and call graphql.Do. The return value carries a Data field and an Errors slice, and the example marshals the whole result to JSON, printing {"data":{"hello":"world"}}.

The mechanism worth noticing is that resolution is per field. Each field in the schema can carry a Resolve function that receives a graphql.ResolveParams and returns a value or an error. In the example the resolver ignores its input and returns the string "world". For a real schema the resolver is where you hit a database, call another service, or read a value off a parent object.

The repository files hint at the machinery underneath. plan.go, plan_cache.go and plan_cache_normalize.go suggest that execution plans are built and cached, and plan_cache_normalize_test.go implies some normalization happens before a plan is reused. The README does not document this cache, so treat it as an implementation detail you can read in the source rather than a configuration surface. The executor_*.go and rules_*.go test files map to the execution and validation stages you would expect from a graphql-js-style engine.

## Installing graphql-go/graphql and running a first query

The README gives one install command and no configuration step. Run it inside a Go module; the repository's own go.mod declares go 1.21, so a toolchain at or above that version is the safe assumption.

```bash
go get github.com/graphql-go/graphql
```

The README then supplies a complete program: a schema with a single hello field of type graphql.String, a query string, and a call to graphql.Do. The trimmed version below keeps the schema and query parts and drops the imports for length.

```go
fields := graphql.Fields{
	"hello": &graphql.Field{
		Type: graphql.String,
		Resolve: func(p graphql.ResolveParams) (interface{}, error) {
			return "world", nil
		},
	},
}
rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
schema, err := graphql.NewSchema(schemaConfig)
if err != nil {
	log.Fatalf("failed to create new schema, error: %v", err)
}
```

Executing a query is a second step. The README passes the schema and the request string into graphql.Params and calls graphql.Do, then checks len(r.Errors) before marshalling the result. Expect the printed output to be {"data":{"hello":"world"}}.

```go
query := `{ hello }`
params := graphql.Params{Schema: schema, RequestString: query}
r := graphql.Do(params)
if len(r.Errors) > 0 {
	log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
}
```

That is the entire documented path. The README does not show how to wire graphql.Do into an HTTP handler, so pairing it with net/http or a router is left to you. It points at examples/ for more complex cases, and lists examples/hello-world, examples/http, examples/http-post, examples/httpdynamic, examples/crud, examples/star-wars and examples/todo among the directories in the repository.

## The HTTP layer and Relay support live outside the module

The README's Third Party Libraries table is the clearest statement of where the project's boundary sits. graphql-go-handler is described as middleware to handle GraphQL queries through HTTP requests, and graphql-relay-go as a library to construct a graphql-go server supporting react-relay. Both are credited to Hafiz Ismail, and both are separate repositories.

That matters for adoption decisions. You are not installing one dependency; you are installing an engine and then choosing whether to add a handler on top. If your team already has a router and wants to control the request lifecycle, the absence of a server package is a feature. If you expected a single module that mounts a GraphQL endpoint and speaks to Relay clients out of the box, the README sends you to code the project does not maintain itself.

The same table lists dataloader by Nick Randall as a DataLoader implementation in Go. Batching and per-request caching of resolver calls is a common requirement in GraphQL servers, and the project's answer is to point at that library rather than to ship one. There is also a single blog post listed, Golang + GraphQL + Relay, which is external to the repository.

## Where the documentation runs out

The README states that the library supports queries, mutations and subscriptions, then never explains subscriptions. There is no example, no mention of a transport, and no discussion of how a subscription is delivered to a client. For a feature that changes how a server is deployed, that gap is significant. Anyone planning to use subscriptions should read the source and the test files rather than rely on the README.

Versioning is the second gap. The most recent release listed is v0.8.1 from 2023-04-10, and the repository's last push was on 2026-06-23. Commits continue while tagged releases have not moved in over three years, so if you depend on version tags you are pinning to a snapshot that predates whatever landed on master. The module path in go.mod is github.com/graphql-go/graphql with no major-version suffix, which is consistent with a pre-1.0 library: the README gives no compatibility promise and no deprecation policy.

On maintenance, the facts are narrow. The repository is not archived, and its last push was on 2026-06-23. That is what can be said. The README does not describe a release cadence, a support window, or a roadmap.

## graphql-go/graphql against gqlgen and the graphql-js model

The obvious comparison in the Go ecosystem is gqlgen, which takes the opposite approach: you write the schema in SDL and it generates Go code from it. graphql-go/graphql has you write the schema in Go and skip generation. The difference shows up when the schema changes. With a generated approach you edit SDL and re-run the generator; here you edit Go structs and let the compiler check the result. Neither is strictly better, but the trade-off is real: generated code gives you a schema file that non-Go tooling can read, while a Go-defined schema keeps everything in one language and one build step.

The README's own reference point is graphql-js, the JavaScript reference implementation. Following it means behaviour is intended to track the reference semantics for parsing, validation and execution. It does not mean the JavaScript ecosystem's tooling comes along. GraphQL Playground, for instance, is a browser client that talks to an HTTP endpoint; since this library ships no endpoint, using a playground with it means writing the HTTP layer first, or adopting graphql-go-handler. The related searches around playgrounds and Postman describe client-side tools, and this project is on the server side of that line.

If your team is not writing Go, the comparison is moot. A Python or Java service has its own GraphQL libraries, and the README makes no claim to be useful outside Go.

## Licence and the cost of staying current

The repository is MIT licensed. For most teams that is the permissive end of the spectrum: it allows use in proprietary software provided the copyright notice and permission notice are preserved. This is a description of the licence identifier, not legal advice; if your organisation has a policy on open-source dependencies, run the MIT text past whoever enforces it.

The upgrade cost is the part worth weighing. Because tagged releases have been static since v0.8.1 while commits continue, there are two ways to consume the library. Pin to a tag and accept that you are on a 2023 snapshot, or track master and accept that you have no version boundary between your build and upstream changes. The go.mod file declares go 1.21, so a toolchain upgrade is a separate consideration from the library version.

There is no documented migration guide in the README, and no statement about what a future v1.0 would change. Budget for reading the diff yourself, or for staying on the tag.

## Conclusion

Adopt graphql-go/graphql if your service is already Go and you want the schema expressed in Go types rather than in SDL plus generated code; the README's hello-world example is the whole setup. Do not adopt it if you need a ready-made HTTP handler or a maintained Relay integration, since the README points at third-party projects for both. Before committing, check that graphql.Do fits your request path and confirm in the repository that the subscription support you need is present, because the README states only that subscriptions are supported.

## FAQ

### What is graphql-go/graphql used for?

It is a GraphQL implementation for Go that follows the graphql-js reference implementation. The README states that it supports queries, mutations and subscriptions, and the example executes a query against a schema defined in Go code.

### Is graphql-go/graphql better than REST?

The README makes no comparison to REST and gives no guidance on when to choose either. It presents the library as an implementation of the GraphQL specification, so the REST versus GraphQL decision is left entirely to the reader.

### How do I install graphql-go/graphql?

The README gives a single command, go get github.com/graphql-go/graphql, and no further setup. The repository's go.mod declares go 1.21.

### How do I use graphql-go/graphql in a Go program?

Define fields and an object config, build a schema with graphql.NewSchema, then pass the schema and a request string in a graphql.Params value to graphql.Do. The README's example checks the returned Errors slice before marshalling the result to JSON.

### Can I use graphql-go/graphql with Postman or a GraphQL playground?

The README does not mention either tool. It lists graphql-go-handler as third-party middleware for handling queries over HTTP, and without an HTTP endpoint a browser or desktop client has nothing to connect to.

## Sources

- [graphql-go/graphql on GitHub](https://github.com/graphql-go/graphql)
- [Issues](https://github.com/graphql-go/graphql/issues)
- [License: MIT](https://github.com/graphql-go/graphql/blob/master/LICENSE)
- [README](https://github.com/graphql-go/graphql/blob/master/README.md)
- [Releases](https://github.com/graphql-go/graphql/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/graphql-go-graphql
