Back to Blog
Lesson 8 of the GraphQL: Your First GraphQL Schema & Server course
API ArchitectureJuly 26, 20264 min read

Implementing Relationships in SDL: Modeling Connected Data

Learn how to define nested object types and link them using GraphQL schema fields. Master the art of representing real-world relationships in your API.

GraphQLSchemaData ModelingAPI ArchitectureSDLBackend
Vibrant orange lines and dots form an abstract network on a dark background, evoking technology and connectivity.

Previously in this course, we covered Defining Custom Object Types: Mastering Data Modeling in GraphQL, where we learned to create standalone entities. In this lesson, we add depth to our schema by establishing connections between those entities, allowing us to model the complex web of data that powers real-world applications.

The Power of Nested Types

In Understanding the GraphQL Schema: Building Your API Contract, we discussed how the Schema Definition Language (SDL) acts as a blueprint for your API. While scalar fields like String or Int are the building blocks, relationships are the structure that makes the data meaningful.

By defining nested object types, you allow a client to traverse your data graph. Instead of making multiple round trips to a server to fetch a user and then their specific posts, a client can ask for a user and embed the related posts in a single request. This is the core of efficient data modeling in GraphQL.

Linking Types in the Schema

To link two types, you simply use the name of one custom type as the field type for a field inside another object.

Consider our ongoing project: a blog platform. We have a User and a Post. A user creates posts, creating a natural association.

GraphQL
type User {
  id: ID!
  username: String!
  email: String!
}

type Post {
  id: ID!
  title: String!
  content: String!
  # Linking the User type here
  author: User!
}

In the example above, the Post type now has an author field. Instead of being a primitive scalar (like a String containing a user ID), the type is explicitly set to User. This tells the GraphQL engine: "When you fetch a post, you can also fetch the full User object associated with that post."

Worked Example: Building a Comment System

Let’s extend our project by adding a Comment type that links back to a Post.

GraphQL
type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

type Comment {
  id: ID!
  text: String!
  # Every comment belongs to a specific post
  post: Post!
}

By defining these relationships, you create a traversable graph. A client can now write a query that looks like this:

GraphQL
query {
  comment(id: "1") {
    text
    post {
      title
      author {
        username
      }
    }
  }
}

Practice Exercise

Add an Address type to your current project. Update your User type to include an address field of type Address.

  1. Define an Address object with fields street, city, and zip.
  2. Update your User type to include an address field.
  3. Consider: What happens if a user doesn't have an address? We will cover nullability in a future lesson, but for now, think about how this relationship changes how you query a user.

Common Pitfalls

  • Circular Dependencies: While GraphQL supports circular references (e.g., User has posts, Post has author), be careful not to create infinite loops in your queries. Use your schema to define the relationship, but rely on your resolvers to handle the actual data fetching.
  • Assuming Database Structure: A GraphQL relationship does not need to mirror your database's Foreign Key columns perfectly. The schema is an abstraction for the client; the implementation inside your resolvers can fetch data from anywhere (REST APIs, databases, or cache).
  • Over-nesting: Just because you can nest objects infinitely doesn't mean you should. Ensure your schema design reflects the way your client application actually needs to consume the data to avoid performance bottlenecks.

FAQ

Does defining a relationship in SDL automatically fetch the data? No. SDL is just the contract. You must write the resolver logic to fetch the associated object when that field is requested.

Can a field be a list of another object type? Yes. You can use square brackets (e.g., posts: [Post!]!) to define one-to-many relationships. We will explore this in the next lesson.

Do I need to store the ID of the related object? It depends. In your backing data storage (like a SQL database), you usually store a foreign key. In your GraphQL API, you expose the object itself to make the graph traversable for the client.

Recap

Relationships allow you to model interconnected data in GraphQL. By using custom types as field types, you enable clients to traverse the data graph, reducing the need for multiple API calls. You’ve moved from simple primitive fields to creating a true API contract that represents your domain model.

Up next: Using Lists for Collections

Similar Posts