The Dream Query: Consumer-First GraphQL API Design

cover
Jens Neuse

Jens Neuse

min 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.

Introducing WunderGraph Hub: Rethinking How Teams Build APIs

WunderGraph Hub is our new collaborative platform for designing, evolving, and shipping APIs together. It’s a design-first workspace that brings schema design, mocks, and workflows into one place.

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:

1
2
3
4
5
6
7
8
9
10
11
12

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Notice what's different.

  • displayName instead of firstName + lastName because the consumer doesn't care about the split
  • department is an object rather than an ID, because the consumer wants the name
  • manager is a resolved user rather than an ID reference
  • recentActivity appears directly on the user, with no separate endpoint
  • createdAt and updatedAt are absent because they aren't needed

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?

  • displayName doesn't exist, so it needs to be added.
  • department as an object, currently there is only departmentId.
  • recentActivity doesn't exist on User at all.
Step 2: Design the schema change.

Add the missing types and fields to the supergraph:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Step 3: Decompose into subgraph responsibilities.

Now figure out who builds what:

  • displayName β†’ Users team (simple computed field)
  • department as object β†’ Department team provides the entity, Users team extends with the relationship
  • manager β†’ Users team (already has managerId, just needs to resolve it)
  • recentActivity β†’ Activity tracking team, extends the User entity

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-firstDream query-first
departmentId: ID!department: Department!
firstName + lastNamedisplayName
managerId: IDmanager: User
Separate /activity endpointrecentActivity on User
Fields exposed because they existFields 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)

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.

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.

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.


Jens Neuse

Jens Neuse

CEO & Co-Founder at WunderGraph

Jens Neuse is the CEO and one of the co-founders of WunderGraph, where he builds scalable API infrastructure with a focus on federation and AI-native workflows. Formerly an engineer at Tyk Technologies, he created graphql-go-tools, now widely used in the open source community. Jens designed the original WunderGraph SDK and led its evolution into Cosmo, an open-source federation platform adopted by global enterprises. He writes about systems design, organizational structure, and how Conway's Law shapes API architecture.