The Dream Query: Consumer-First GraphQL API Design - WunderGraph

Jens Neuse

CEO & Co-Founder at WunderGraph

March 14, 2026·5min read

Every API starts with a question. The question is usually: "What data can our service expose?"

But that's the wrong question.

The right question is: "What is the consumer trying to achieve?"

This approach to schema design, starting from the consumer ( consistent with GraphQL’s product-centric design philosophy), changes everything about how your API ends up looking.

The Problem With Backend-Out API Design

Here's how most APIs get built.

A backend team has a service, and they expose the fields that already exist in their database model:

type User @key(fields: "id") {
  id: ID!
  firstName: String!
  lastName: String!
  email: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  role: UserRole!
  departmentId: ID!
  managerId: ID
  isActive: Boolean!
}

This is a perfectly reasonable schema. It maps to the database model and every field is accurate.

But it's designed from the backend out.

The field is called departmentId because that is the foreign key in the database. If a consumer wants the department name, they need to make a second query. managerId returns only an ID and the consumer has to resolve it themselves. createdAt and updatedAt are exposed because they exist, not because anyone asked for them.

Now multiply this across 50 subgraphs, where each team exposes what they have. The supergraph is a concatenation of database models. Technically correct. Practically painful.

What Is a Dream Query?

A dream query is the query the consumer would write if there were no technical constraints.

Instead of asking "What can we expose?", ask the frontend team: "If you could query anything, what would the ideal query look like?"

For a user profile page, they could write:

query UserProfile($id: ID!) {
  user(id: $id) {
    displayName
    email
    role
    department {
      name
      head {
        displayName
      }
    }
    manager {
      displayName
      email
    }
    recentActivity(limit: 5) {
      description
      timestamp
    }
  }
}

Notice what's different.

This query is a specification. It tells you exactly what the API should look like from the perspective of someone who will use it.

Working Backwards

Once you have the dream query, you work backwards.

Step 1: Identify the gaps.

Compare the dream query to your current supergraph. What exists? What's missing?

Step 2: Design the schema change.

Add the missing types and fields to the supergraph:

Step 3: Decompose into subgraph responsibilities.

Now figure out who builds what:

This is where Fission automates the mechanical work. The architect assigns new types and fields to subgraphs, and Fission handles the consequences. Hub routes the proposals to affected teams for review.

Why Dream Queries Produce Better APIs

When you design from the backend out, the API reflects implementation details. Foreign keys can leak through, internal names persist, and the consumer has to understand how the backend works to use the API effectively.

When you design from the dream query, the API reflects consumer intent. Names are meaningful. Relationships are resolved.

Some concrete differences in schema design:

Backend-first Dream query-first
departmentId: ID! department: Department!
firstName + lastName displayName
managerId: ID manager: User
Separate /activity endpoint recentActivity on User
Fields exposed because they exist Fields exposed because they're needed

The dream query approach also catches design problems early. If the dream query requires data from three different teams, you discover that before implementation, not after.

Who Should Write the Dream Query?

The dream query is a conversation starter, not a frontend-only tool.

Product owners can describe what a feature needs without knowing GraphQL syntax. "The profile page shows the user's name, their department, their manager, and recent activity." That's a dream query in plain English.

Mobile developers have different needs than web developers. Their dream queries might request less data or different fields optimized for smaller screens. Both queries inform the same supergraph design.

AI agents are the newest consumer. An agent's "dream query" is whatever data it needs to complete a task. Agents benefit most from consumer-first schema design because they can't compensate for bad naming or missing relationships the way a human developer can.

A Practical Starting Point

You don't need special tooling to start using dream queries.

Next time a team requests a schema change, ask them: "What's your dream query? If you could query anything, what would it look like?"

Write it down. Compare it to your current supergraph. Note the gaps.

Even without automating the decomposition, this conversation changes the dynamic. It shifts schema design from "what can the backend expose?" to "what should the consumer experience?"

That shift in perspective is the most valuable part.

With Hub, you can take this further. The visual canvas lets teams propose dream queries, see how they map to the existing graph, identify gaps, and create proposals — all in one place.

But the principle works regardless of tooling. For more on designing schemas around what clients need, see our principles for designing good GraphQL schemas.

Start with the consumer. Design the query they'd want to write. Then figure out how to build it.

Frequently Asked Questions (FAQ)

What is a dream query?
A dream query is the GraphQL query a consumer would write if there were no technical constraints. It represents the ideal API from the consumer perspective and serves as the starting point for API design, rather than backend service structure.

Who writes the dream query?
Anyone who consumes the API: frontend engineers, product owners, mobile developers, or even AI agents. The point is that API design starts with the consumer, not the backend team.

Does this only work with GraphQL?
The concept applies to any API design, but GraphQL makes it practical because the query language naturally expresses consumer intent. With REST, there is no standard way to express "this is the data I want" independent of endpoint structure.