In GraphQL, a schema is the backbone of your API—it defines the structure, functionality, and types of data that clients can query, mutate, or subscribe to. The schema acts as a contract between the client and server, ensuring that both parties understand what data is available, how it can be manipulated, and the relationships between various data types.
The schema is made up of types, which describe the shape of data.
Fields within types specify what data can be requested and returned.
The schema is typically written in Schema Definition Language (SDL), which is a syntax designed specifically for defining GraphQL schemas.
The GraphQL schema is the foundation of every GraphQL API. It serves as the authoritative source of truth that defines what data can be queried, what operations can be performed, and the relationships between different types. Written in the GraphQL Schema Definition Language (SDL), the schema provides a clear, self-documenting contract that enables clients to understand exactly what the API offers. Unlike REST, where documentation is often separate, the GraphQL schema itself is the documentation—tools can automatically generate documentation, perform validation, and enable powerful IDE integrations like autocomplete and type checking.
Root Operation Types: The entry points to the schema. Every GraphQL schema must define at least a Query type, and may optionally define Mutation and Subscription types. These define the operations clients can perform.
Object Types: The fundamental building blocks representing real-world entities. Each object type has fields, and each field has a type. Fields can be scalar (String, Int, Boolean, Float, ID) or other object types, enabling complex nested queries.
Scalar Types: Primitive types that represent leaf values. GraphQL includes five built-in scalars: Int, Float, String, Boolean, ID. Custom scalars can be defined for specialized needs like Date or JSON.
Input Types: Special object types used exclusively for mutation arguments. Input types cannot contain fields that are other object types—they can only contain scalars, enums, or other input types.
Enums: A restricted list of allowed string values, useful for status fields or categorization.
Interfaces: Abstract types that define a set of fields that must be implemented by any object type that implements the interface. Enables polymorphic queries.
Unions: Similar to interfaces but without shared fields. A union type can be one of several object types, useful for search results or heterogeneous collections.
The GraphQL Schema Definition Language (SDL) uses a concise, readable syntax. Types are defined with the type keyword, fields are listed with their types and nullability markers (! indicates non-null, [] denotes lists). Arguments can be specified for fields. The type Query definition is special—it defines the entry point for all read operations. The type Mutation follows the same pattern but for write operations. This declarative syntax makes schemas easy to write, review, and version.
Backward Compatibility: Adding new fields is safe; removing fields is breaking. Mark deprecated fields with @deprecated directive rather than removing them.
Nullability: Be conservative with ! (non-null). Adding a non-null field to an existing type breaks existing queries that don't request that field.
Input Types: Prefer input types over multiple scalar arguments for mutations, making them easier to extend.
Versioning: Unlike REST, GraphQL APIs typically don't use version numbers. Instead, evolve the schema in a backward-compatible way.
Tooling: Use schema linters to enforce consistency and catch breaking changes before deployment.
In large organizations, a single GraphQL schema may be composed from multiple services. Apollo Federation allows multiple GraphQL services (subgraphs) to be composed into a single unified schema. Each subgraph defines its part of the schema, and a gateway stitches them together. This enables team autonomy while presenting a single API to clients. The schema becomes a distributed contract across services, requiring careful coordination of type definitions and reference resolvers.