Backend Development 15 min read

Using GraphQL to Reduce API Calls and Manage Data Complexity in Frontend Development

The article explains how the rapid growth of API endpoints and data fields in complex business scenarios can be mitigated by introducing a GraphQL middle‑layer built with Node.js, detailing schema design, resolvers, performance considerations, tooling, custom scalars, response formatting, caching, and security measures.

HomeTech
HomeTech
HomeTech
Using GraphQL to Reduce API Calls and Manage Data Complexity in Frontend Development

When facing complex business scenarios, the number and complexity of interfaces can become a major pain point for engineers. In the overseas business of a car‑related platform, the frontend team applied GraphQL for the first time to address this issue, accumulating a series of practical experiences.

Typical data structures for a video page include fields such as { video_url: 'https://video.domain.com/1', title: 'Manstory Urus', author: 'jerry', isFollow: 0, brand_id: 1, series_id: 1, tags: ['ferrari'] } . Adding new requirements—like recommended vehicles or like counts—leads to additional fields and new API endpoints, increasing the number of requests and risking redundant data transmission to PC and mobile clients.

To reduce the number of API calls and filter redundant fields, the team proposes a frontend‑centric middle‑layer built with Node.js . Node.js offers low learning cost for frontend developers, event‑driven non‑blocking I/O, and fits the IO‑intensive nature of API aggregation. GraphQL aligns perfectly with these needs.

GraphQL basics are introduced: a type‑system‑driven query language that provides a complete description of available data. Its schema defines object and array types, while resolvers bridge the schema to data sources. Example schema and resolver snippets are shown: type Query { user(userid: Int!): User company(company_id: Int!): Company } type User { userid: Int! name: String company: [Company] } type Company { company_id: Int! name: String } schema { query: Query } Query: { user: async (_, { userid }, { dataSources }) => dataSources.userAPI.getUserInfo({ userid }) }

On the client side, a lightweight wrapper around request is used to send GraphQL queries, avoiding heavy libraries like Apollo when the existing codebase is large. A typical request looks like: request({ url: 'http://test.autohome.com.cn/GraphQL', body: { query: ` query getUserInfo($userid: 1) { user(userid: $userid) { userid name company { company_id name } } }` , operationName: "getUserInfo" } })

For merging multiple independent requests, GraphQL allows a single query containing several root fields, which the server resolves in parallel: query getUserInfo($userid: Int!, $goodid: Int!) { user(userid: $userid) { userid name } goods(goodid: $goodid) { goodid name price } order(userid: $userid) { orderid price createtime } }

When dependencies exist between queries, the schema can embed nested types and resolvers can fetch dependent data, as demonstrated with a user‑order‑goods example.

Performance considerations include the extra hop introduced by GraphQL. By keeping the GraphQL server and backend services on the same internal network, the added latency is negligible. Persistent queries (APQ) are handled by hashing the query string (sha256) and caching it on the server, allowing GET requests to send only the hash and falling back to POST when the hash is unknown.

Useful tooling includes Apollo Server Playground, graphql‑ide, and altair‑graphql‑client for debugging, as well as json2schema for converting JSON responses into GraphQL schemas.

Advanced topics cover custom scalars (e.g., BigInt ) to handle numbers beyond 32‑bit integers, response formatting to align GraphQL output with the team's existing returncode / result convention, and security hardening such as limiting parallel query depth, nesting depth, and disabling public debugging tools.

Cache control for data sources is addressed by configuring apollo-datasource-rest with cacheOptions.ttl = 0 and clearing memoized results after each response to avoid stale data.

In summary, adopting GraphQL enables effective control over frontend request volume, removal of redundant fields, and a flexible data‑fusion layer that reduces backend coupling while maintaining performance and security.

BackendfrontendperformanceNode.jsAPI optimizationGraphQL
HomeTech
Written by

HomeTech

HomeTech tech sharing

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.