GraphQL, resolved
in plain Go.
Your structs are the schema and your methods are the resolvers. grx serves them as a fast GraphQL API with subscriptions, persisted queries and guard rails, from an ordinary http.Handler.
Response
Resolving
0/6 fields
Structs are the schema
Your Go types already describe your API.
grx reads your structs and methods once at startup and builds the schema clients see. Hover a line to follow the edge from Go to GraphQL.
type User struct {ID string `gql:"id,nonNull"`Name string `gql:"name,nonNull"`Bio *string `gql:"bio"`}type UserArgs struct {ID string `gql:"id,nonNull"`}type Query struct{}func (Query) User(ctx context.Context, args UserArgs) (*User, error)type Subscription struct{}func (Subscription) UserUpdated(ctx context.Context) (<-chan *User, error)
type User {id: String!name: String!bio: String}type Query {user(id: String!): User}type Subscription {userUpdated: User}
Exported methods on Query become fields: User → user.
Batteries, wired in
Everything is an option on one handler.
Start with a schema. Add realtime, auth and guard rails as the service grows, without adopting a framework.
srv, err := grx.NewServer( grx.WithSchema(graph.Schema()), grx.WithTransports(websocket.New(), sse.New()), grx.WithPlugins(logger), grx.WithPersistedQueries(trusted), grx.WithFieldAuthorizer(requireViewer), grx.WithMaxSelectionDepth(12),)
Fits your stack
grx owns GraphQL. You own everything else.
Routing, TLS, CORS, auth extraction and your database stay where they already live. grx sits in the middle of the request and nowhere else.
Your router
net/http, Chi, Gin, Echo, Fiber
Transport
HTTP, WebSocket, SSE
Parse
persisted queries
Validate
depth & size limits
Execute
authorizers, plugins
Your resolvers
plain Go methods
Benchmarks
Same queries. A fraction of the work.
parse → validate → execute → JSON on identical fixtures for grx, graph-gophers and graphql-go. grx does it with far fewer allocations, so there is less GC pressure under real traffic.
Nested query
post(id) → author
12.7×
Feed timeline
feed → posts → author
4.5×
Persisted compound
fragments, aliases, variables
4.1×
Five minutes
From empty folder to a live API.
- One module: go get it. Go 1.25 or newer.
- GraphiQL built in: on any path you choose.
- Plain JSON over HTTP: so any GraphQL client works, or curl.
❯
Your turn
Resolve your first query today.
Open source, MIT licensed, and built to live inside the Go service you already run.