Features
GraphQL extension capabilities
GraphQL Interface
The extension exposes a GraphQL interface for programmatic schema management and query execution:
type GraphQL interface {
RegisterType(name string, obj interface{}) error
RegisterQuery(name string, resolver FieldResolverFunc) error
RegisterMutation(name string, resolver FieldResolverFunc) error
RegisterSubscription(name string, resolver SubscriptionResolverFunc) error
GenerateSchema() (string, error)
GetSchema() *GraphQLSchema
ExecuteQuery(ctx context.Context, query string, variables map[string]interface{}) (*Response, error)
HTTPHandler() http.Handler
PlaygroundHandler() http.Handler
Use(middleware Middleware)
EnableIntrospection(enable bool)
Ping(ctx context.Context) error
}Resolver Registration
Register queries, mutations, and subscriptions programmatically:
// Query resolver
server.RegisterQuery("users", func(ctx context.Context, args map[string]interface{}) (interface{}, error) {
limit := 10
if l, ok := args["limit"].(int); ok {
limit = l
}
return db.ListUsers(ctx, limit)
})
// Mutation resolver
server.RegisterMutation("createUser", func(ctx context.Context, args map[string]interface{}) (interface{}, error) {
return db.CreateUser(ctx, args["name"].(string), args["email"].(string))
})
// Subscription resolver (returns a channel)
server.RegisterSubscription("messageAdded", func(ctx context.Context, args map[string]interface{}) (<-chan interface{}, error) {
ch := make(chan interface{})
go func() {
defer close(ch)
for msg := range messageStream {
ch <- msg
}
}()
return ch, nil
})Schema
Auto-generate a GraphQL schema from registered resolvers, or load from a schema file:
// Auto-generate
schema, _ := server.GenerateSchema()
// Or load from file
graphql.NewExtension(
graphql.WithSchemaFile("schema.graphqls"),
)The GraphQLSchema struct includes: Types, Queries, Mutations, Subscriptions, and Directives.
Interactive Playground
Built-in GraphQL IDE served at a configurable endpoint for exploring the API during development:
graphql.NewExtension(
graphql.WithPlayground(true),
graphql.WithPlaygroundEndpoint("/playground"),
)Access the playground at http://localhost:8080/playground.
Query Protection
Complexity Limits
Reject queries that exceed a configurable complexity score (default 1000). Prevents abusive deeply nested queries:
graphql.NewExtension(graphql.WithMaxComplexity(500))Depth Limits
Reject deeply nested queries beyond a configurable depth (default 15 levels):
graphql.NewExtension(graphql.WithMaxDepth(10))Query Timeout
Per-request timeout enforced via context deadline (default 30 seconds):
graphql.NewExtension(graphql.WithQueryTimeout(10 * time.Second))Query Caching
Cache parsed and validated query plans to avoid re-parsing identical queries:
EnableQueryCache-- enable/disable (default: true)QueryCacheTTL-- cache entry TTL (default: 5 minutes)MaxCacheSize-- max cached queries (default: 1000)
DataLoader Integration
Built-in N+1 query prevention. DataLoaders batch individual lookups into efficient bulk queries:
// DataLoader interface
type DataLoader interface {
Load(key string) (interface{}, error)
LoadMany(keys []string) ([]interface{}, []error)
Prime(key string, value interface{})
Clear(key string)
ClearAll()
}
// Create a loader with batch function
loader := dataloader.NewLoader(
dataloader.DefaultLoaderConfig(),
func(keys []string) (map[string]interface{}, error) {
return db.BatchGetUsers(keys)
},
)Configuration:
DataLoaderBatchSize-- max keys per batch (default: 100)DataLoaderWait-- wait time to collect keys before executing batch (default: 10ms)
Executor Middleware
Chain middleware functions on the GraphQL execution pipeline:
server.Use(func(next graphql.ExecutorFunc) graphql.ExecutorFunc {
return func(ctx context.Context, req *graphql.Request) (*graphql.Response, error) {
start := time.Now()
resp, err := next(ctx, req)
log.Printf("Query took %v", time.Since(start))
return resp, err
}
})Programmatic Query Execution
Execute queries from server-side code:
result, err := server.ExecuteQuery(ctx, `
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`, map[string]interface{}{"id": "123"})File Uploads
Support multipart file uploads with configurable max size (default 10 MB).
CORS Support
Configurable allowed origins for cross-origin requests:
graphql.NewExtension(
graphql.WithCORS(true),
graphql.WithAllowedOrigins([]string{"https://app.example.com"}),
)Slow Query Logging
Log queries that exceed a configurable threshold (default 1 second). Helps identify performance bottlenecks.
Introspection Control
Disable introspection for production security:
server.EnableIntrospection(false)Observability
- Metrics -- request count, latency histograms, error rates
- Tracing -- distributed tracing via OpenTelemetry
- Logging -- structured logging of queries and errors
Federation
Built-in federation support:
graphql.NewExtension(
graphql.WithFederation(graphql.FederationConfig{Enabled: true, Version: "2.0"}),
)Sentinel Errors
| Error | Meaning |
|---|---|
ErrNotInitialized | Server has not been initialized |
ErrInvalidQuery | Query string is malformed |
ErrInvalidSchema | Schema definition is invalid |
ErrTypeNotFound | Requested GraphQL type not found |
ErrResolverNotFound | No resolver for the requested field |
ErrExecutionFailed | Query execution failed |
ErrComplexityExceeded | Query complexity exceeds limit |
ErrDepthExceeded | Query depth exceeds limit |
ErrTimeout | Query exceeded timeout |
ErrInvalidConfig | Configuration validation failed |
How is this guide?