The Dream Query: Consumer-First GraphQL API Design

Jens Neuse
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.
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:
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.
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:
Notice what's different.
displayNameinstead offirstName+lastNamebecause the consumer doesn't care about the splitdepartmentis an object rather than an ID, because the consumer wants the namemanageris a resolved user rather than an ID referencerecentActivityappears directly on the user, with no separate endpointcreatedAtandupdatedAtare 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.
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?
displayNamedoesn't exist, so it needs to be added.departmentas an object, currently there is onlydepartmentId.recentActivitydoesn't exist onUserat all.
Add the missing types and fields to the supergraph:
Now figure out who builds what:
displayNameβ Users team (simple computed field)departmentas object β Department team provides the entity, Users team extends with the relationshipmanagerβ Users team (already hasmanagerId, just needs to resolve it)recentActivityβ Activity tracking team, extends theUserentity
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.
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.
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.
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
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.

