Skip to content

// Communication & Integration · 03

GraphQL

Client queryleads toOne endpointleads toExactly the fields

The client asks for exactly the shape it needs, in one round trip.

How it fits together

GraphQL structure«client»Web appquery { order { total } }gets total back only«client»Mobile app/graphql endpointone URL, many queriesdepth and cost capsResolversDataLoader batchingprojectionsOrdersCustomersProducts1 query1 query2 resolvefetchfetchfetch
uses / calls· numbered steps replay in order
  • Web app uses / calls /graphql endpoint (1 query)
  • Mobile app uses / calls /graphql endpoint (1 query)
  • /graphql endpoint uses / calls Resolvers (2 resolve)
  • Resolvers uses / calls Orders (fetch)
  • Resolvers uses / calls Customers (fetch)
  • Resolvers uses / calls Products (fetch)

Spot it

  • A screen needs five calls to render one view
  • Payloads carry fields nobody displays
  • Every new screen asks for a new endpoint

It costs

Flexible for clients, but harder to cache, secure and keep fast on the server.

In code

public sealed class CustomerByIdLoader(    ICustomerRepository customers,    IBatchScheduler scheduler,    DataLoaderOptions options)    : BatchDataLoader<Guid, Customer>(scheduler, options){    protected override async Task<IReadOnlyDictionary<Guid, Customer>> LoadBatchAsync(        IReadOnlyList<Guid> keys,        CancellationToken cancellationToken) =>        await customers.GetByIdsAsync(keys, cancellationToken);}​public sealed class OrderResolvers{    public ValueTask<Customer?> GetCustomerAsync(        [Parent] Order order,        CustomerByIdLoader loader,        CancellationToken cancellationToken) =>        loader.LoadAsync(order.CustomerId, cancellationToken);}
Go deeperThe full explanation and what to ask for · 1 min readExpand

A typed schema describes the whole graph; clients send a query naming the fields they want and get exactly that back. Resolvers fetch each field, so one request can combine data from several sources.

The classic mistake is naive resolvers: a list of 50 orders, each resolving its customer, issues 51 queries. Batch with DataLoader. The other is accepting arbitrary queries: a deep or wide query can be very expensive, so cap depth and cost, or allow only persisted queries.

Most requests are POSTs to one URL, so HTTP caching and per-endpoint metrics no longer apply out of the box. GraphQL often serves as the aggregation layer of a backend for frontend, sitting over REST or gRPC services.

Ask for it

  • schema
  • query / mutation / subscription
  • resolver
  • DataLoader
  • depth and cost limits
  • persisted queries

Add a GraphQL endpoint at /graphql over Orders, Customers and Products: batch resolvers with DataLoaders to avoid N+1, enable projections and cursor pagination, cap query depth at 8 and cost per request, and accept only persisted queries in production.