Request Deduplication
April 13, 2026 ยท View on GitHub
Deduplication is provided as an optional plugin.
For the canonical option/type reference, see api.md -> Deduplication Plugin.
Import
import { createClient } from '@fetchkit/ffetch'
import {
dedupePlugin,
dedupeRequestHash,
} from '@fetchkit/ffetch/plugins/dedupe'
Usage
const client = createClient({
plugins: [dedupePlugin()],
})
const p1 = client('https://api.example.com/data')
const p2 = client('https://api.example.com/data')
const [r1, r2] = await Promise.all([p1, p2])
// One network request, shared in-flight promise.
Configuration
const client = createClient({
plugins: [
dedupePlugin({
hashFn: (params) => `${params.method}|${params.url}|${params.body}`,
ttl: 30_000,
sweepInterval: 5_000,
}),
],
})
Options
hashFn: Custom key function. Returnundefinedto skip dedupe for a request.ttl: Optional map-entry eviction TTL in milliseconds.sweepInterval: Sweeper interval in milliseconds whenttlis enabled.order: Plugin execution order override.
Behavior Notes
- Deduplication is off unless the plugin is installed.
- The dedupe key is computed from the original request init/body before dispatch; if
transformRequestchanges request identity, use a customhashFnthat reflects the final semantics you need. - TTL eviction only removes in-flight dedupe keys from the map.
- TTL eviction does not reject already in-flight request promises.
- Stream/FormData request bodies are skipped by the default hash strategy.
Defaults
hashFn:dedupeRequestHashttl:undefined(disabled)sweepInterval:5000order:10
Breaking Migration
Removed legacy options:
dedupededupeHashFndedupeTTLdedupeSweepInterval
Use plugins: [dedupePlugin(...)] instead.