Back to Blog
Lesson 24 of the GraphQL: Your First GraphQL Schema & Server course
API ArchitectureAugust 11, 20264 min read

The Root Query Type: GraphQL Schema Entry Points Explained

Learn how to define the Query type in your GraphQL schema. Master the root entry point that dictates how clients access your API's data.

GraphQLSchemaQuerySDLBackend
Wooden letters spelling the word "QUESTIONS" on a cardboard background, providing a neutral copyspace.

Previously in this course, we explored Defining Custom Object Types and Implementing Relationships in SDL to model our domain. Now that we have our data shapes defined, we need a way to actually access them.

In GraphQL, you can't simply "query" an object type directly. You need a designated gateway. That gateway is the Query type.

The Query Type as the API Entry Point

In GraphQL, your schema is more than just a collection of types; it is a map of what your server can do. The Query type is a special object type in the Schema Definition Language (SDL) that serves as the root of all read operations.

Think of your entire schema as a tree. The Query type is the trunk. If a field isn't reachable starting from the Query type, the client will never be able to access that data. Even if you have a User type or a Product type perfectly defined, they remain invisible to the client until you "register" them as fields on the Query type.

Defining the Root Query

To make data available, you must explicitly declare a type Query in your SDL. Every field inside this block is an entry point.

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

type Query {
  # These are the entry points
  me: User
  allUsers: [User!]!
}

In this example, the client can now send a query to fetch me or allUsers. They cannot, however, query a User object directly because it isn't defined under the Query root.

Registering Root-Level Queries

Close-up of tree roots in a sunlit forest, showcasing natural textures and greenery.

Registering a root-level query involves two steps: declaring the field in your SDL and implementing the corresponding function in your resolver map.

Let’s look at how this connects to our server implementation:

JAVASCRIPT
const typeDefs = CE9178">`#graphql
  type User {
    id: ID!
    username: String!
  }

  type Query {
    me: User
  }
`;

const resolvers = {
  Query: {
    me: () => {
      return { id: "1", username: "dev_student" };
    },
  },
};

When the server receives a request for me, it looks at the Query object in your resolver map, executes the me function, and returns the data that matches the User shape.

When to add a field to Query

A common question is: "Should every object be on the root query?" The answer is no. You should only put fields on the Query type if they represent:

  1. A specific resource lookup (e.g., user(id: ID!)).
  2. A collection (e.g., posts).
  3. A singleton (e.g., viewer, settings).

If data is inherently nested—like a Comment belonging to a Post—you shouldn't put comments on the root query unless you specifically need to fetch them globally. Instead, use the relationships you learned about in Implementing Relationships in SDL.

Hands-on Exercise: Exposing Your Data

In your current project, assume you have a Book type. Your task is to:

  1. Define a type Query block in your typeDefs.
  2. Add a field called featuredBook that returns a Book.
  3. Update your resolvers object to include a Query property.
  4. Implement the featuredBook resolver to return a hardcoded object matching the Book structure.

Common Pitfalls

Close-up of a triangular warning sign indicating a slippery surface, fixed to a wooden post.

  • Forgetting the Query Type: If you define types but omit the type Query, your server will fail to start or return an error because it has no entry point.
  • Case Sensitivity: In SDL, type Query must be capitalized. If you name it type query, the GraphQL engine will not recognize it as the root entry point.
  • Multiple Query Types: You can only have one type Query block in your schema. If you have a large schema, you must define the type once and append fields to it, or use schema merging techniques (which we will cover in Organizing Schema Files).

FAQ

Can I name the root query something else? No. The Query type is a reserved name in the GraphQL specification for the root of all read operations.

What if I want to change data? Changing data happens through the Mutation type, which is the peer of the Query type. We will dive into that in future lessons.

Does every field in Query need a resolver? Yes. Since the Query type is the entry point, the server relies on your resolvers to fetch the initial data for those fields.

Recap

Team members presenting a project in a modern office setting with a focus on collaboration.

The Query type is the mandatory entry point for all data fetching. By registering fields under this root, you expose your domain models to the client. Keep your root clean by only exposing necessary entry points, and rely on nested resolvers for relational data.

Up next: Querying Lists with Arguments where we will make our entry points dynamic.

Similar Posts