One request,
exactly the fields the screen needs
A mobile app screen that needs a user, their recent orders and a product recommendation in one view has two options. It can make three separate REST calls and stitch them together, or send one GraphQL query that asks for exactly that shape. We build GraphQL where screens genuinely vary in what they need, not as a default replacement for a simpler REST API.
What it is
GraphQL is an API query language where a client specifies exactly which fields it needs, across potentially several related entities, in one request. The server resolves that query and returns exactly that shape, nothing more, nothing less. REST works differently. Each endpoint returns a fixed shape, and a client often needs several requests stitched together to assemble a full screen’s worth of data. GraphQL instead lets the client’s actual data need drive the request.
When you need this (and when you don’t)
It earns its cost when different clients, or different screens within the same product, need meaningfully different, often nested, data shapes from the same underlying entities. Think a mobile app screen needing a lean subset of fields on a slow connection, and a desktop dashboard needing the same entities with far more detail. A multi-vendor marketplace platform we built benefits from exactly this. A seller dashboard, a buyer-facing storefront and an admin view all need different slices of the same product and order data.
It’s the wrong tool for a simple API with a small number of clear resource types and one main consumer. REST is simpler to build, simpler to cache at the HTTP level, and easier for a new developer to reason about without learning a query language first. We recommend REST as the default. We reach for GraphQL specifically when the variable-data-shape problem is real, not because it’s the more interesting technology to build.
How we build it
Schema design is the real engineering work in a GraphQL API. We map the schema to actual business entities and the real relationships between them, not a one-to-one copy of database tables. A schema that just mirrors the database exposes implementation details a client should never need to know about. We do this with both the frontend team and the backend team in the room, since the schema is the contract both sides will live with.
Resolver batching gets built in from the start using DataLoader or an equivalent, specifically to avoid the N+1 query problem. Naively resolving a list of items triggers one database query per item, instead of one batched query for the whole list. This is the single most common performance mistake we’ve seen in GraphQL APIs during audits. It’s far cheaper to prevent than to retrofit once a query pattern is already in production.
Authorization happens at the field level where the data actually requires it. A query for a product might expose different fields depending on whether the requester is the seller, an admin, or a public visitor. That’s resolved per field, not per endpoint. We also set query complexity limits. GraphQL’s flexibility means a client, malicious or just careless, can construct a single deeply nested query far more expensive than any REST endpoint would allow. An API without a complexity limit has no real ceiling on that.
What to watch
GraphQL’s caching story is genuinely more complex than REST’s. A REST GET request caches cleanly at the HTTP and CDN level. A GraphQL query over POST needs its own caching strategy, usually at the resolver or data-loader level rather than the transport level. We plan this explicitly, rather than discovering it as a performance problem after launch.
Query complexity limits and rate limiting need to be real, not theoretical. GraphQL’s expressiveness is exactly what makes an unprotected endpoint a bigger liability than an equivalent REST API. A schema that grows without discipline, fields added ad hoc for one screen’s convenience, becomes just as tangled as the REST sprawl GraphQL was meant to avoid. We review schema changes against the same entity model discipline from the first version onward.
Price and timeline
| Option | Price | What it covers | Timeline |
|---|---|---|---|
| Core schema and API | from $4,000 | Schema design, batched resolvers, authorization | 3 to 5 weeks |
| Multi-client API with complexity limits | from $9,000 | Several consuming apps, query complexity limits, caching strategy | 5 to 7 weeks |
Running cost is backend hosting, typically $30 to $250 a month depending on query volume and complexity.
What this pairs with
This pairs with API-first backend with OpenAPI as the alternative contract style worth comparing before committing. It also pairs with websocket real-time features when some of the same data needs live updates too. See the development service page for our full build process. For real examples, see the multi-vendor marketplace platform and ProBay’s marketplace infrastructure.
Stitching together several REST calls per screen right now? Get in touch and we will tell you honestly if GraphQL is actually the fix.
FAQ
How much does a GraphQL API cost?
From $4,000 for a schema covering your core entities, with batched resolvers and authorization, in 3 to 7 weeks. A larger API serving a complex marketplace or multi-app product runs $8,000 to $16,000.
Should we use GraphQL or REST?
GraphQL earns its cost when clients, especially mobile apps on variable connections, need different nested data shapes per screen and reducing request count matters. The same goes when several frontends need different subsets of the same data. REST is simpler to build, cache and reason about, and it remains the better default for most APIs. We assess your actual client needs honestly rather than defaulting to whichever is more fashionable.
What is the N+1 problem and do I need to care?
It's a common GraphQL performance bug. Resolving a list of items triggers one database query per item, instead of one batched query for all of them. That can quietly turn a reasonable API into a slow one under real load. We build resolver batching with DataLoader or an equivalent from the first version, specifically to avoid this, rather than fixing it after a performance complaint.
Can different users see different fields?
Yes. Field-level authorization is a core part of schema design. A public query might expose a product's name and price while hiding internal cost data. That's resolved per field based on who's asking, not just per endpoint the way REST authorization usually works.
Who owns the schema and the server?
You. The GraphQL schema, resolvers and server code live in your repository. Schema documentation is generated automatically, so it never falls out of sync with what the API actually serves.