gqlparser: the Go port of the GraphQL reference parser
A port of the parser from graphql-js into golang
At a glance
- What is it?
- gqlparser is a Go implementation of the GraphQL parser and validator that mirrors the graphql-js reference implementation closely while staying idiomatic, and it is the parser behind gqlgen. It tracks the September 2025 specification plus selected portions of the draft, ships a formatter, a lexer, an error package with error paths and extensions, and a property based test suite, and it is MIT licensed with patch releases landing several times a week.
- Who is it for?
- gqlparser fits a Go team that needs to parse, validate and format GraphQL documents and wants behaviour that matches the reference implementation rather than a dialect of its own, and it fits anyone building on gqlgen, which already depends on it. It does not fit a team that wants a full GraphQL server, since this is a library with no execution engine, and it does not fit a project that has to track a brand new specification revision on its own schedule.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the project is and who depends on it
gqlparser is a parser for GraphQL, written to mirror the graphql-js reference implementation as closely as possible while remaining idiomatic and easy to use. It is written in Go, the module path is github.com/vektah/gqlparser/v2, and it requires Go 1.25.
The dependency fact is the most important line in the project description: this parser is used by gqlgen, the 99designs code generation framework, and it should be reasonably stable. That single sentence tells you a great deal about the maintenance expectations. A library that another widely used tool depends on for its core function cannot release breaking changes on a whim, and the guiding principles listed in the project description make that explicit in the first item, maintainability, because it should be easy to stay up to date with the specification.
The four other principles explain the rest of the design. It should be well tested, and the wording is specific: it shouldn't need a GraphQL server to validate itself, and changes to the repository should be self contained. That is a rule about testing architecture, and it is the reason the test suite lives in this repository rather than in the server project that consumes it.
It should be server agnostic, usable by any of the GraphQL server implementations and any GraphQL client tooling, which rules out tying the AST to one framework's runtime types. It should have an idiomatic and stable API following Go best practices, especially around forwards compatibility, which is a GraphQL problem as much as a Go one because clients in the field send queries against servers they did not build. And it should be fast, where that does not impact the above, by avoiding unnecessary allocations in hot paths.
The last principle is the one that causes the most discussion in this kind of port, and it is stated with its own escape clause: close to the reference implementation, where it doesn't impact on the above. The escape clause is what allows the port to stay Go-flavoured while still behaving like graphql-js.
The project is MIT licensed, the repository is not archived, and the last push was on 2026-10-20.
How the project tracks the GraphQL specification
The specification target is stated precisely, and that precision is the thing that distinguishes a maintained port from a one-off port.
The project targets the September 2025 specification and select portions of the Draft, based on the graphql-js reference implementation at version 16.13.2. The named features that follow from that target are the Schema definition language, block strings as descriptions, and error paths and extensions.
The interesting mechanism is the update process. The description says that if there is a specification update or a new release, you should follow the documented process to update and submit a pull request. The process lives in the validator's imported documentation, in a directory named validator/imported/ inside the tree, which tells you something about the layout: the validator's rule set is imported from the specification material rather than written from scratch, and the readme in that directory is the procedure for pulling in a new revision of it.
That structure is why the project can claim to be easy to stay up to date with the specification. The specification's validation rules are numerous and change in small ways, and re-implementing them by hand at every revision is where ports usually rot. Importing them and keeping the Go rendering in step is a much smaller job, and the fact that the imported material is versioned in the repository means the project can pin the specification revision it was written against.
The reference implementation version matters for the same reason. Pinning to graphql-js v16.13.2 rather than tracking the tip of that repository means the behaviour of this port is defined at a point in time, and when a new graphql-js release lands, the same update procedure applies.
The other thing this design buys is the error package, gqlerror, which carries error paths and extensions. Those are the parts of a GraphQL error response a client needs in order to say which field of which query failed, and having them match the reference implementation's shape means a client written against the JavaScript ecosystem works unchanged against a Go server.
The package layout, from lexer to formatter
The top level of the tree shows the pipeline laid out as separate packages, and the names are the best available map of the library.
The `lexer/` directory holds the tokenizer, the `parser/` directory holds the parser itself, the `ast/` directory holds the abstract syntax tree types, and the `validator/` directory holds the rule checking. Those four are the core of the library and the dependency order runs left to right.
Alongside them there are two packages that are not part of the parse path but are part of why you would use this library rather than write a parser. `gqlerror/` is the error type with paths and extensions, and `formatter/` is a printer for the AST. The formatter is the one that gets underestimated. Being able to take a query and print it back in canonical form is what lets a tool offer a pretty-print button, and doing that without a full GraphQL implementation is exactly the kind of thing a port makes cheap.
The `validator/imported/` directory is the mechanism described earlier, holding the imported specification rules and the procedure for updating it.
Then there is the testing infrastructure, which is the most telling part of the listing. There is a `proptest/` directory, which is Go property based testing, a `testdata/` directory holding fixtures, a `gqlparser_bench_test.go` and a `benchmark_doc_test.go` at the top level, and the benchmark file being at the root rather than inside a package suggests the benchmarks are run against the public API.
Property based testing is the right tool for a parser, because it lets you generate inputs and assert invariants rather than assert on fixed examples, and the presence of a `proptest/` package in a parser repository is a sign of how seriously the author takes correctness.
The remaining entries are the ordinary project furniture. There is a `.golangci.yaml` for linting, a `.goreleaser.yaml` for release builds, a `.go-version` and a `.mise.toml` for toolchain pinning, a `.prettierignore` and a `.mdformat.toml` for the two Markdown formatters, a `.vale.ini` for prose linting and a `.rumdl.toml` for another Markdown linter, a `.shellcheckrc`, a `.mutago.yml`, a `.editorconfig` and a `.circleci/` directory for CI. The presence of three separate Markdown linters is a small but real signal about the project's culture.
There is also a `WIP.md` at the top level, which is an unusual file to see and suggests the author keeps an explicit list of unfinished work in the repository rather than only in issues.
Release cadence, retracted versions and dependency choices
The release pattern here is unusual and worth understanding before you pin a version.
The recent releases are v2.5.61 on 2026-10-07, v2.5.62 on 2026-10-08 and v2.5.63 on 2026-10-14, with the last push on 2026-10-20. That is two or three patch releases a week, and it is a direct consequence of the project tracking a specification and a reference implementation that both move. When graphql-js publishes a fix or a specification draft is revised, this port has to move with it, and it moves in small increments rather than in a quarterly batch.
The go.mod file shows the other side of that policy, and it is the part to notice. There is a retract directive listing v2.5.14 and v2.5.13. Retracting a version tells the Go module tooling not to select it, so if you have those versions in a go.sum, the tooling will warn you. Two consecutive versions were retracted, which tells you the project found problems serious enough to pull from users rather than patch forward.
The dependency list is deliberately short for a GraphQL library. The direct requirements are github.com/agnivade/levenshtein for edit distance, github.com/stretchr/testify for assertions, and go.yaml.in/yaml/v3 for YAML. There is no GraphQL framework, no schema registry client, no HTTP layer and no code generation dependency. The levenshtein package is there for the error suggestions that GraphQL implementations typically offer, where a validation error points at the nearest valid token, and that is a small, well-scoped dependency rather than a general string library.
The YAML dependency is worth noting because it is not in the GraphQL specification. It is there for the schema definition language that the project says it supports, which in practice means loading SDL from a YAML file as well as from a GraphQL document.
The test dependencies are equally minimal. testify for assertions and levenshtein are the only non-standard packages, and the property based tests rely on the standard library's testing package with the proptest helper, so the self-contained testing principle is visible in the dependency graph rather than just stated.
Where gqlparser is the wrong choice
The first limit is that this is a parser and a validator, not a server. There is no execution engine, no resolver interface, no subscription handling, no query planner and no HTTP transport. If you want to serve GraphQL, you want gqlgen, which is the tool built on this parser, or another server implementation. Using gqlparser directly means writing the execution layer yourself.
The second is the fidelity trade. The project is deliberately close to graphql-js, which is a strength for compatibility and a constraint for a Go-native design. Where the reference implementation does something JavaScript-shaped, this port has to decide whether to copy the behaviour or to be idiomatic, and the guiding principles put maintainability and closeness to the reference ahead of idiomatic Go in the cases where they conflict. A team that wants a Go-flavoured AST with different node types will not get it here.
The third is the release churn. Two or three releases a week is good for getting a specification fix quickly and bad for reproducibility, because a go.mod that says a version range can pick up a new patch without anyone deciding to. The retract mechanism partly addresses this, and it also means the module proxy will warn you about versions you have. In a build pipeline where a GraphQL parser change must not alter generated server code, you want to pin exactly and update deliberately.
The fourth is the Go version floor. The module requires Go 1.25, so this is not a library you can drop into an older toolchain, which is usually fine today and occasionally a problem in a long-lived build image.
Compare that with writing a GraphQL parser yourself, or with using a Go GraphQL library that includes its own parser. The difference in approach is that gqlparser gives you a battle-tested parser whose behaviour matches the reference implementation, that other Go tools depend on, and that you can rely on staying current, whereas a bundled parser inside a server framework gives you one fewer dependency but a parser that is coupled to that framework and updated at its pace. The choice is between a shared component and a private one, and the shared component is better tested and worse pinned.
Licence, upgrade notes and what to check before you depend on it
gqlparser is released under the MIT licence, with the LICENSE file in the repository root. MIT is one of the most permissive terms, it has no copyleft obligation and no patent grant beyond the licence itself, and for a parsing library that most teams will vendor into a server binary it is a straightforward choice. You should read the LICENSE file yourself for the exact terms.
The project describes itself as reasonably stable, and the API guidance is worth taking seriously if you are going to build on it. The idiomatic and stable API principle says the API should follow Go best practices, especially around forwards compatibility, and in a GraphQL context forwards compatibility has a specific meaning. A client sends a query with a field your server does not know about, or a fragment spread, or a variable, and the parser has to represent the document faithfully enough that your validation layer can produce a useful error rather than a parse failure. An AST that quietly drops the parts it does not understand is worse than one that fails loudly, and the principle is aimed at that.
There is a WIP.md in the repository root, and the release tags are the reference for a specific version, with each point release maintained as a tag. The project description says that if you require a specific version, refer to those tags.
What to check before you depend on it is a short list. Pin an exact version rather than a range, because the release frequency means a floating version is a moving target, and check the retract list in the module file so you know which versions to avoid.
Then check the specification target against what you need. The project targets the September 2025 specification plus select portions of the Draft, and if your schema uses a feature from a draft that is not in the selected portions, you need to know that now rather than when a query fails to parse.
If you are on an older v2 major of the library, read the migration documentation for that path, since the module path carries the v2 suffix and the API has changed across the major version. And if you intend to keep up with specification revisions yourself rather than waiting for the maintainer, read the update procedure in validator/imported, because that document is the contract for how a new specification draft is turned into Go rules in this repository.
Editorial conclusion
gqlparser fits a Go team that needs to parse, validate and format GraphQL documents and wants behaviour that matches the reference implementation rather than a dialect of its own, and it fits anyone building on gqlgen, which already depends on it. It does not fit a team that wants a full GraphQL server, since this is a library with no execution engine, and it does not fit a project that has to track a brand new specification revision on its own schedule. Before you adopt it, pin a specific v2.5.x release, since the project retracts bad versions and tags two or three times a week, and read the validator import process document before assuming your copy of a specification draft is current.
Frequently asked questions
What is gqlparser and who uses it?
gqlparser is a Go parser for GraphQL, written to mirror the graphql-js reference implementation closely while staying idiomatic. It is the parser used by gqlgen, the 99designs code generation framework, and the project says it should be reasonably stable.
Which GraphQL specification does gqlparser implement?
It targets the September 2025 specification and select portions of the Draft, based on the graphql-js reference implementation at version 16.13.2. That includes the Schema definition language, block strings as descriptions, and error paths and extensions, with a documented process for following a new specification update or graphql-js release.
What packages does the gqlparser module contain?
The tree separates the work into `lexer/`, `parser/`, `ast/` and `validator/`, plus `gqlerror/` for errors carrying paths and extensions, a `formatter/` package for printing the AST, `validator/imported/` holding the imported specification rules, and a `proptest/` directory for property based tests alongside `testdata/` fixtures and benchmark files.
What licence is gqlparser released under and how often does it release?
The project is released under the MIT licence, with the licence text in the repository root. Releases are frequent, with v2.5.61 on 2026-10-07, v2.5.62 on 2026-10-08 and v2.5.63 on 2026-10-14, and the module file retracts v2.5.13 and v2.5.14.
Does gqlparser include a GraphQL server or execution engine?
No. It is a parser, validator, error package and formatter, with no execution engine, resolver interface or HTTP transport. To serve GraphQL in Go you would use gqlgen, which is built on this parser, or another server implementation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vektah-gqlparser)Was this useful?