How to Speed Up Legacy APIs with Node.js, GraphQL, Redis, and Scheduling
This article walks through a practical approach for front‑end engineers to cut down a sluggish legacy API from over three seconds to under a second by adding a Node.js proxy layer that leverages GraphQL field selection, Redis caching, and a scheduled cache refresh.
Background
Legacy API returns massive payloads (over 1000 records, each with hundreds of fields) and performs many downstream calls, resulting in average latency greater than 3 seconds.
Solution Overview
A Node.js proxy layer introduces three optimizations without modifying the original service code:
On‑demand field selection using GraphQL.
Result caching with Redis.
Periodic cache refresh using node‑schedule.
1. On‑Demand Loading with GraphQL
Define a data pool (root), a GraphQL schema that describes the required fields, and execute queries that request only the needed attributes. The example below uses a mock "girls" dataset to illustrate the process.
var root = { girls: [{ id: 1, name: '女神一', iphone: 12345678910, weixin: 'xixixixi', height: 175, school: '剑桥大学', wheel: [{ name: '备胎1号', money: '24万元' }, { name: '备胎2号', money: '26万元' }] }, { id: 2, name: '女神二', iphone: 12345678910, weixin: 'hahahahah', height: 168, school: '哈佛大学', wheel: [{ name: '备胎3号', money: '80万元' }, { name: '备胎4号', money: '200万元' }] }] }; const { buildSchema } = require('graphql');
var schema = buildSchema(`
type Wheel { name: String, money: String }
type Info { id: Int, name: String, iphone: Int, weixin: String, height: Int, school: String, wheel: [Wheel] }
type Query { girls: [Info] }
`); const { graphql } = require('graphql');
const query = `{ girls { name weixin } }`;
const result = await graphql(schema, query, root);Nested queries are also supported:
const query = `{ girls { name wheel { money } } }`;
const result = await graphql(schema, query, root);2. Caching with Redis
Cache the aggregated result of the legacy endpoint in Redis so that subsequent requests can read directly from the cache, bypassing expensive downstream logic.
const redis = require('redis');
const { promisify } = require('util');
const client = redis.createClient(6379, '127.0.0.1');
const getAsync = promisify(client.get).bind(client);
const setAsync = promisify(client.set).bind(client);
async function list() {
let result = await getAsync('cache');
if (!result) {
const data = await oldInterface(); // call legacy API
await setAsync('cache', JSON.stringify(data));
result = data;
}
return JSON.parse(result);
}
list();3. Periodic Refresh with node‑schedule
Use a scheduled job (e.g., hourly) to refresh the Redis entry, keeping cached data consistent with the source.
const schedule = require('node-schedule');
schedule.scheduleJob('* * 0 * * *', async () => {
const data = await oldInterface();
await setAsync('cache', JSON.stringify(data));
});Results
After applying the three techniques, API response time dropped from roughly 3 seconds to about 860 ms, delivering a noticeably smoother user experience.
Reference implementation (GitHub): https://github.com/airuikun/blog/tree/master/src/graphql%2Bredis
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent Cloud Developer
Official Tencent Cloud community account that brings together developers, shares practical tech insights, and fosters an influential tech exchange community.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
