12 Writing Your First GraphQL Schema File
12 Writing Your First GraphQL Schema File
Written by: An engineer who once got lost in the jungle of RESTful APIs
GraphQL has become the API of choice for many engineering teams, not only because of its flexible queries but also thanks to its highly explicit type system. For newcomers, however, figuring out how to write your first schema file can feel intimidating. Don’t worry, in this article I’ll walk you through it step by step until you have your very first, ready-to-test GraphQL schema.
What Is a GraphQL Schema File?
Put simply, a GraphQL schema file (*.graphql or *.gql) is the blueprint of your API. In it you describe what data types are available, which fields can be queried, and which operation types (Query, Mutation, Subscription) are supported.
A GraphQL schema is typically written in the Schema Definition Language (SDL) format.
Flow Diagram: The GraphQL Schema in the API Lifecycle
Let’s start with the big picture first. Here is a simple flow (using Mermaid):
flowchart TD
A[Client mengirim query] --> B[Server memetakan ke skema GraphQL]
B --> C[GraphQL Resolver menangani logic]
C --> D[Data dikembalikan ke client]
The key point: the schema is the contract between the client and the server.
Case Study: A Book API
Imagine your team wants to build a simple API for book and author data. The initial functionality consists of:
- Fetching a list of books
- Fetching the details of a book
- Adding a new book
Let’s map those requirements onto a schema.
1. Start with the Basic type
Think about the main entities: books and authors.
1type Book {
2 id: ID!
3 title: String!
4 author: Author!
5 year: Int
6}
7
8type Author {
9 id: ID!
10 name: String!
11 books: [Book!]!
12}Explanation:
- The Boolean, String, Int, Float, and ID data types are available by default.
!marks a field as required (it cannot be null).
| Type | Description | Required? |
|---|---|---|
| ID | Unique identifier | Yes |
| String | Text (title, name) | Yes |
| Int | Publication year | No |
2. Define the Query
Read (read/fetch) operations are the domain of type Query.
1type Query {
2 books: [Book!]!
3 book(id: ID!): Book
4 authors: [Author!]!
5}With this, the client can perform:
books→ Get all booksbook(id: ...)→ Get the details of a single bookauthors→ Get all authors
Example query:
1query {
2 books {
3 id
4 title
5 author {
6 name
7 }
8 }
9}3. Add a Mutation
To add data, use type Mutation.
1type Mutation {
2 addBook(title: String!, authorId: ID!, year: Int): Book
3}Example mutation:
1mutation {
2 addBook(title: "Clean Code", authorId: "1", year: 2008) {
3 id
4 title
5 }
6}4. Assemble It into a Single Schema
Your schema.graphql file now looks roughly like this:
1type Book {
2 id: ID!
3 title: String!
4 author: Author!
5 year: Int
6}
7
8type Author {
9 id: ID!
10 name: String!
11 books: [Book!]!
12}
13
14type Query {
15 books: [Book!]!
16 book(id: ID!): Book
17 authors: [Author!]!
18}
19
20type Mutation {
21 addBook(title: String!, authorId: ID!, year: Int): Book
22}5. Validate with a Tool
It’s recommended to use GraphQL Playground or a VSCode extension such as Apollo GraphQL. Copy and paste the schema above, and your server is ready to accept queries and mutations.
6. Resolver Simulation (Pseudocode)
The important part after the schema: the resolver (the handler logic). Here’s an example in JavaScript (Node.js):
1const resolvers = {
2 Query: {
3 books: () => db.books,
4 book: (_, { id }) => db.books.find(b => b.id === id),
5 authors: () => db.authors,
6 },
7 Mutation: {
8 addBook: (_, { title, authorId, year }) => {
9 const book = { id: uuid(), title, author: authorId, year };
10 db.books.push(book);
11 return book;
12 }
13 },
14 Book: {
15 author: (book) => db.authors.find(a => a.id === book.author),
16 },
17 Author: {
18 books: (author) => db.books.filter(b => b.author === author.id),
19 }
20};7. Expand It!
GraphQL is highly flexible. You can extend the schema however you like; let’s add a new field, for example rating:
1type Book {
2 ...
3 rating: Float
4}Or a new type, for example Review, and then relate it to Book.
8. Practical Tips for Writing Schemas
- Modular: Split large types into their own files (
book.graphql,author.graphql), then import them (using a tool such as Apollo/GraphQL-tools). - Comments: Use the
#symbol to write comments so the schema stays clear and well documented. - Enum: Use an Enum for fields with a limited set of options (for example, status).
1enum BookStatus {
2 AVAILABLE
3 OUT_OF_STOCK
4 DELETED
5}- InputType: For complex input on a mutation, declare a separate input type.
1input BookInput {
2 title: String!
3 authorId: ID!
4 year: Int
5}9. Testing: Query Table
Here is a comparison table of queries and responses based on the schema you’ve built:
| Query | Response Sample |
|---|---|
books { id, title } | [ {id: "1", title: "GraphQL in Action"}, ... ] |
book(id: “2”) { title, author {name}} | { "title": "Clean Code", author: { "name": "Bob" } } |
10. When Should the Schema Be Changed?
Changing the schema (for example, adding a new field) is best done:
- After discussing the requirement with the client
- After validating the data model
- Following versioning, in the case of a breaking change
11. Schemas and Automatic Documentation
The schema is the API documentation. Tools like GraphQL Playground, Apollo Studio, or Voyager will display the API from that schema automatically.
12. Review: A 5-Point Checklist to Validate Your Schema
| Checklist | Recommendation |
|---|---|
| Data types are explicit | Don’t leave a field as a plain String; model it more specifically when you can |
| Relations between types are defined | Use reference fields |
| Mutation inputs are clear and safe | Use an InputType |
| Critical types/fields have comments | Make it easier for other readers |
| Responses are predictable (required/optional) | Mark required fields with ! |
Conclusion
The GraphQL schema is the core foundation of a modern API. Take the time to design it before coding the resolvers. Modularize your schema, write comments, and discuss it with your team. With the 12 steps above, I hope you’re not only able to write your first schema file, but also ready to build a GraphQL API that is solid, expandable, and easy to maintain.
If you have other tips or want to request a follow-up topic, please leave a comment. Happy GraphQL-ing! 🚀