Deduplicate Concurrent Client Requests
Share one in-flight promise among callers of the same resource so a burst of identical requests hits the network once.
Task
Stop a UI that triggers the same fetch from many components from issuing duplicate network calls.
When to use this
Several components mount at once, each calls the same endpoint, and the app sends many identical requests that all resolve with the same data.
Prerequisites
- A promise-based HTTP client
- A key derived from the request
Steps
1. Key each request by method and URL plus relevant headers.
Expected output: Identical requests share a key.
2. Keep a map of in-flight promises and return the existing one when present.
Expected output: Concurrent callers await a single network call.
3. Remove the entry in a finally block so later callers can refetch.
Expected output: Deduplication does not cache forever.
4. Distinguish this from caching: dedup only merges concurrent, not sequential, calls.
curl -s https://api.example.com/user/me -o /dev/null -w "%{http_code}"Expected output: The behavior is predictable.
Troubleshooting
Problem
Stale shared result
Solution
Remove the promise on settle; do not keep it as a permanent cache.
Problem
Different auth tokens share a key
Solution
Include the authorization scope in the key so cross-user requests never merge.
Limitations
- Deduplication only helps concurrent requests; it does nothing for sequential repeats.
- It must not merge requests with different bodies for non-idempotent methods.
Context
Stop a UI that triggers the same fetch from many components from issuing duplicate network calls. Several components mount at once, each calls the same endpoint, and the app sends many identical requests that all resolve with the same data.
Steps
- Key each request by method and URL plus relevant headers. Expected: Identical requests share a key.
- Keep a map of in-flight promises and return the existing one when present. Expected: Concurrent callers await a single network call.
- Remove the entry in a finally block so later callers can refetch. Expected: Deduplication does not cache forever.
- Distinguish this from caching: dedup only merges concurrent, not sequential, calls. Expected: The behavior is predictable.
const inflight = new Map();
function get(url) {
const key = `GET ${url}`;
if (!inflight.has(key)) {
inflight.set(key, fetch(url).finally(() => inflight.delete(key)));
}
return inflight.get(key);
}
Verify
- Identical requests share a key.
- Concurrent callers await a single network call.
- Deduplication does not cache forever.
- The behavior is predictable.
Limits
- Deduplication only helps concurrent requests; it does nothing for sequential repeats.
- It must not merge requests with different bodies for non-idempotent methods.