The N+1 query problem in Go GraphQL is solved by batching data loaders to execute a single query per type instead of one per field. Implement a DataLoader that collects all requested IDs during the resolve phase and executes one aggregated database query.
type UserLoader struct {
batchFunc func(ctx context.Context, keys []string) ([]*User, []error)
cache map[string]*User
}
func (l *UserLoader) Load(ctx context.Context, id string) (*User, error) {
if u, ok := l.cache[id]; ok {
return u, nil
}
// Trigger batch if not cached (simplified logic)
users, errs := l.batchFunc(ctx, []string{id})
if len(users) > 0 {
l.cache[id] = users[0]
return users[0], nil
}
return nil, errs[0]
}
func (r *QueryResolver) Users(ctx context.Context) ([]*User, error) {
// Fetch all users in one query
allUsers, err := db.FindAllUsers(ctx)
if err != nil {
return nil, err
}
// Populate loader cache
loader := &UserLoader{cache: make(map[string]*User)}
for _, u := range allUsers {
loader.cache[u.ID] = u
}
return allUsers, nil
}