Schema-First Design
You'll learn to
- -Write GraphQL types, scalars, and the non-null (!) modifier correctly
- -Explain why the schema is the actual contract in GraphQL, replacing the role many separate REST endpoint definitions play
A REST API's contract is spread across every endpoint's individual request/response shape. GraphQL inverts this: there is exactly one schema, describing every type and every possible query/mutation the API supports, and every client request is validated against that single schema before it ever executes.
Types and Scalars
type User {
id: ID!
name: String!
email: String!
age: Int
isVerified: Boolean!
orders: [Order!]!
}
type Order {
id: ID!
total: Float!
placedBy: User!
}- -GraphQL's built-in scalars: `Int`, `Float`, `String`, `Boolean`, `ID` (a unique identifier, serialized as a string but semantically distinct from `String`).
- -A custom type (`User`, `Order`) is a named object composed of fields, each with their own type.
- -A field's type can be another object type, letting the schema express relationships (`orders: [Order!]!`) the same way a foreign key expresses a relationship in a database schema.
The Non-Null Modifier: A Deliberate, Consequential Choice
A `!` after a type means the field can never be `null` - the server guarantees it will always return a value if the query includes that field at all. This sounds like a minor detail, but getting it wrong in either direction has real cost: marking a field non-null that later turns out to need to be nullable is a breaking schema change (existing clients assumed it could never be null and may not handle a sudden `null`), while marking everything nullable "to be safe" pushes null-checking onto every single client for data that, in practice, is always present.
type User {
name: String! # every User always has a name - clients never null-check this
bio: String # bio is genuinely optional - clients must handle nullThe Query Root
type Query {
user(id: ID!): User
users(limit: Int, offset: Int): [User!]!
order(id: ID!): Order
}The `Query` type is the schema's entry point - every field on it is a top-level query a client can run, each with its own arguments (like `id: ID!` for a single-user lookup). Everything reachable from a `Query` field's return type (here, all of `User`'s fields, and transitively `Order`'s fields through `orders`) becomes queryable in a single request, which is the structural source of GraphQL's "ask for exactly what you need, in one round trip" property.
Treat non-null as a promise you have to keep for the schema's entire lifetime, not a default to reach for reflexively - when genuinely unsure whether a field could ever legitimately be absent, nullable is the safer starting point, since loosening a non-null field later is a breaking change but tightening a nullable one rarely is.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Design Schema Genesis in the API Design Lab's GraphQL Mastery act.