Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
14 Oct 2025 · 5 min read ·Article 106 / 125
Go

106 Writing a `.graphqls` Schema for gqlgen

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

106 Writing a .graphqls Schema for gqlgen: A Practical Guide

Using gqlgen to build a GraphQL API in Go not only delivers high performance and flexibility, it also brings us closer to best practice patterns in modern architecture. One of the main foundations when working with gqlgen is writing the GraphQL schema (.graphqls). This article walks you through, step by step, how to design a .graphqls file that is robust, scalable, and optimized for continuous development.


What Is a .graphqls Schema?

A .graphqls file is where we define the shape of our data, queries, mutations, relationships, and the rules surrounding the API. By analogy, .graphqls is the “contract” between the frontend and the backend — defining data types, query endpoints, mutations, and even subscriptions.

Using a .graphqls file means becoming a schema-first developer. You design the API layer before touching any business logic or the database.


The Basic Anatomy of .graphqls

Let’s start with a simple schema that we can use as a reference.

graphql
 1# schema.graphqls
 2
 3type User {
 4  id: ID!
 5  name: String!
 6  email: String!
 7  posts: [Post!]!
 8}
 9
10type Post {
11  id: ID!
12  title: String!
13  content: String!
14  author: User!
15}
16
17type Query {
18  users: [User!]!
19  posts: [Post!]!
20  user(id: ID!): User
21  post(id: ID!): Post
22}

Explanation:

  • We define two main types (User and Post) along with their relationship.
  • There is a Query type that defines the endpoints/output a client can fetch.

Extended: Adding Mutations and Enums

GraphQL is not just about reading data; it also lets you modify data through mutations, as well as use specialized data types such as Enums.

graphql
 1enum Role {
 2  ADMIN
 3  USER
 4  GUEST
 5}
 6
 7type User {
 8  id: ID!
 9  name: String!
10  email: String!
11  role: Role!
12  posts: [Post!]!
13}
14
15type Mutation {
16  createUser(name: String!, email: String!, role: Role!): User!
17  createPost(title: String!, content: String!, authorId: ID!): Post!
18}
Danger

Sample Query:

graphql
1mutation {
2  createUser(name: "Bob", email: "bob@example.com", role: ADMIN) {
3    id
4    name
5  }
6}

How Does gqlgen Use the .graphqls Schema?

When you run the command go run github.com/99designs/gqlgen generate, gqlgen will:

  1. Read every .graphqls file
  2. Build a mapping of Go structures based on the types in the schema
  3. Generate resolver scaffolding that you must implement (for Query, Mutation, and so on)

Flow Diagram (Mermaid)

MERMAID
graph TD
    A[Start] --> B[Edit schema.graphqls]
    B --> C[gqlgen generate]
    C --> D[Generate types.go & resolvers.go]
    D --> E[Implement resolver logic]
    E --> F[API Siap Digunakan]

Schema Modularization Tactics

In large teams or complex applications, splitting up your .graphqls files is a great help for manageability. For example:

FileContents
user.graphqlstype User, User-related Query/Mutation, enum Role
post.graphqlstype Post, Post-related Query/Mutation
schema.graphqlsRoot Query, Mutation, or Subscription

Your folder will look something like this:

text
1- graph/
2    - schema.graphqls
3    - user.graphqls
4    - post.graphqls

gqlgen will automatically merge all .graphqls files within the same folder.


Best Practices for Writing Schemas

  1. Use the Right Scalars:
    Don’t just slap String on every data type. Use Int, Float, Boolean, and custom scalars such as DateTime.

  2. Document Every Field:
    Use """ comment blocks to provide intellisense in tools like GraphQL Playground.

    graphql
    1"""
    2This type represents a user's blog post article.
    3"""
    4type Post {
    5  title: String!
    6  ...
    7}
  3. Use Enums for Limited Value Sets:
    Avoid typos and manual validation by using enums for types such as status, role, and so on.

  4. Modular & DRY:
    Extract input types and payloads once your queries/mutations start getting complex.

    graphql
    1input CreatePostInput {
    2  title: String!
    3  content: String!
    4  authorId: ID!
    5}
    6
    7type Mutation {
    8  createPost(input: CreatePostInput!): Post!
    9}
  5. Backward Compatibility:
    A GraphQL breaking change occurs when you remove a field — always review the new schema carefully before a release.


Real-World Case Simulation

Suppose you need the following features in your application:

  • View the list of users and posts (with the user-to-post relationship)
  • Create a new user
  • Create a new post for a specific user

The schema could look like this:

graphql
 1# user.graphqls
 2
 3type User {
 4  id: ID!
 5  name: String!
 6  email: String!
 7  posts: [Post!]!
 8}
 9
10input NewUserInput {
11  name: String!
12  email: String!
13}
14
15type Mutation {
16  createUser(input: NewUserInput!): User!
17}
graphql
 1# post.graphqls
 2
 3type Post {
 4  id: ID!
 5  title: String!
 6  content: String!
 7  author: User!
 8}
 9
10input NewPostInput {
11  title: String!
12  content: String!
13  authorId: ID!
14}
15
16type Mutation {
17  createPost(input: NewPostInput!): Post!
18}

Conclusion

The .graphqls schema is the primary blueprint in the lifecycle of GraphQL API development with gqlgen. By writing a clean schema, documenting every business use case, and leveraging modularization, you make scaling, maintenance, and engineer-to-engineer handover far easier. More than just a file, the .graphqls schema is the heart of your API contract.

If you have tips or a favorite schema you’d like to share, feel free to discuss them in the comments.
Happy coding, engineer! 🚀

Related Articles

💬 Comments