Photo by PJH on Unsplash

On this page

This chapter follows What is GraphQL.

Every GraphQL service exposes exactly one schema. The schema does not store data or run SQL; it tells the execution engine which operations exist, which types fields return, and which arguments are legal. Clients and tools read that contract to validate documents before they hit the network.

Schema Definition Language

SDL (Schema Definition Language) is the human-readable syntax for types. A minimal service might look like this:

schema.graphql
"""A library catalog entry."""
type Book {
id: ID!
title: String!
publishedYear: Int
}
type Query {
book(id: ID!): Book
books: [Book!]!
}

Descriptions use "..." on a single line or """...""" for multiple lines. They appear in GraphiQL and in generated docs.

The schema must define a Query root type. Mutation and Subscription roots are optional but conventional for writes and live updates.

Root operation types

Root Purpose
Query Read operations; fields run in parallel by default
Mutation Write operations; top-level mutation fields run serially
Subscription Long-lived read streams, usually over WebSockets

Entry points are fields on these roots, not arbitrary URLs:

type Mutation {
createBook(input: CreateBookInput!): Book!
}
type Subscription {
bookAdded: Book!
}

Naming roots Query, Mutation, and Subscription is convention; the spec only requires that the schema declares which object types play those roles.

Schema-first versus code-first

Teams choose how the schema file comes into existence:

Approach Flow Typical stacks
Schema-first Authors edit .graphql SDL, then implement resolvers by hand Apollo Server (SDL + resolvers map), GraphQL Yoga
Code-first Types and fields are declared in code; SDL is generated at build or startup NestJS @nestjs/graphql, Pothos, TypeGraphQL

Neither approach changes what clients see if the emitted SDL is the same. Code-first fits teams that already live in TypeScript and want decorators or builders to stay in sync with resolvers. Schema-first fits teams that treat the SDL file as the source of truth in code review.

Directives and the type system

Built-in directives such as @deprecated(reason: "...") and @specifiedBy(url: "...") attach metadata to schema elements. Custom directives (for example @auth) extend validation or execution in server-specific ways; clients must not rely on unknown directives unless your tooling documents them.

The next chapters walk through object types, scalars, input types, and interfaces in detail. They all compose into the single schema document.

Introspection

Clients can ask the server to describe its own schema with special meta-fields:

{
__schema {
queryType { name }
types { name kind }
}
}

Introspection powers GraphiQL, codegen, and federation composition. It also helps attackers map your API. Production services often disable introspection for anonymous users or expose it only on internal endpoints. Introspection answers what the schema allows; it does not reveal resolver implementation or database layout.

Next: Object types and scalars.

Check your understanding

Question 1 of 5

0 of 5 checked

  1. 1. Which root type must every GraphQL schema define?

Search articles

Type a word to search published articles.

Open the search page