gitlab-org/gitlab
GraphQL API
GitLab's GraphQL endpoint at /api/graphql, with subscriptions at /api/graphql_subscriptions. Most newer features expose data via GraphQL first.
Source
app/graphql/
├── gitlab_schema.rb # The schema; assembles types, mutations, subscriptions
├── batch_loaders/ # BatchLoader pre-loaders
├── directives/ # Custom directives
├── graphql_triggers.rb # Subscription trigger registry
├── mutations/ # ~30 namespaces of mutations
├── queries/ # File-based query helpers
├── resolvers/ # ~40 namespaces of field resolvers
├── subscriptions/ # Subscription definitions
├── types/ # ~80 namespaces of types
├── cached_introspection_query.rb
└── ...
ee/app/graphql/ # EE additionsThe graphql-ruby gem powers the schema. Custom GitLab additions:
- Scope-aware authorization at the field level.
- Complexity scoring with hard limits.
- Polymorphic Apollo-style cache hints.
- Action Cable transport for subscriptions.
- BatchLoader for N+1-free traversal.
Schema
The main schema is GitlabSchema (app/graphql/gitlab_schema.rb). EE features prepend onto it.
Schema artifacts:
bin/rake gitlab:graphql:schema:dumpproducestmp/tests/graphql/gitlab_schema.graphql(and.json).- The persisted SDL ships as a CI artifact; clients (Apollo codegen, the Web IDE) consume it.
- Schema breaking changes are flagged by
Gitlab::Graphql::CompatibilityCheckin CI.
Conventions
- Types are camelCased on the GraphQL side and snake_cased server-side (
graphql-rubyhandles the mapping). - Field-level authorization uses
authorize: :ability_name, which callsdeclarative_policy. - Mutations follow the Relay convention:
MutationInput { clientMutationId, ... }, returnMutationPayload. - Connections use Relay-style cursor pagination.
Mutations
module Mutations
module Projects
class Update < BaseMutation
graphql_name 'ProjectUpdate'
authorize :admin_project
argument :id, ::Types::GlobalIDType[::Project], required: true
argument :description, GraphQL::Types::String, required: false
field :project, ::Types::ProjectType, null: true
def resolve(id:, **args)
project = authorized_find!(id: id)
result = ::Projects::UpdateService.new(project, current_user, args).execute
# …
end
end
end
endSubscriptions
graphql_triggers.rb declares trigger functions that producers call:
GraphqlTriggers.issuable_assignees_updated(issue)Subscribers use Action Cable as the transport; app/channels/graphql_channel.rb routes incoming subscription requests.
Complexity limits
Every field has a complexity score. The total per query is capped (~250 by default; logged-out users have a lower cap). The Gitlab::Graphql::ComplexityAnalyzer enforces this and emits Prometheus metrics.
Persisted queries
GitLab.com supports persisted queries (introspection-cached) via the cached_introspection_query.rb helper. The frontend ships a hashed query manifest; the server validates against it.
Where to make changes
- New type: under
app/graphql/types/<area>/. Always setgraphql_nameand a description. - New mutation: under
app/graphql/mutations/<area>/<verb>.rb. SubclassBaseMutationand useauthorize. - New subscription: declare in
graphql_triggers.rband the subscriptions namespace. - New resolver: under
app/graphql/resolvers/<area>/. UseBatchLoader::GraphQLfor N+1.
Testing
- Request specs under
spec/requests/api/graphql/. - Resolver specs under
spec/graphql/resolvers/. - Mutation specs under
spec/graphql/mutations/. - Helpers in
spec/support/helpers/graphql_helpers.rb.
Related
- REST API.
- Action Cable — subscription transport.
- Frontend — Apollo client.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.