'use strict';
function dedupeAsync(producer, keyFn) {
const pending = new Map();
const resolveKey = keyFn || ((...args) => JSON.stringify(args));
return function deduped(...args) {
const key = resolveKey(...args);
if (pending.has(key)) {
return pending.get(key);
}
const promise = Promise.resolve()
.then(() => producer(...args))
.finally(() => {
pending.delete(key);
});
pending.set(key, promise);
return promise;
};
}
module.exports = { dedupeAsync };
'use strict';
const https = require('https');
const { dedupeAsync } = require('./dedupe');
function fetchUser(id) {
return new Promise((resolve, reject) => {
const url = `https://api.example.com/users/${encodeURIComponent(id)}`;
https
.get(url, (res) => {
if (res.statusCode >= 400) {
res.resume();
return reject(new Error(`HTTP ${res.statusCode} for user ${id}`));
}
let body = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () => {
try {
resolve(JSON.parse(body));
} catch (err) {
reject(err);
}
});
})
.on('error', reject);
});
}
const loadUser = dedupeAsync(fetchUser, (id) => `user:${id}`);
function warm(ids) {
// Duplicate ids in the burst collapse to one upstream call each.
return Promise.all(ids.map((id) => loadUser(id)));
}
module.exports = { loadUser, warm };
'use strict';
const assert = require('assert');
const { dedupeAsync } = require('./dedupe');
async function run() {
let calls = 0;
const producer = (id) =>
new Promise((resolve) => {
calls += 1;
setTimeout(() => resolve(`value-${id}`), 25);
});
const load = dedupeAsync(producer, (id) => String(id));
const results = await Promise.all([load(7), load(7), load(7), load(7)]);
assert.strictEqual(calls, 1, 'producer should run once for concurrent calls');
assert.ok(results.every((v) => v === 'value-7'), 'all callers share the value');
// After settling, the slot is freed, so a new call runs the producer again.
await load(7);
assert.strictEqual(calls, 2, 'later call re-invokes after eviction');
console.log('dedupeAsync: all assertions passed');
}
run().catch((err) => {
console.error(err);
process.exit(1);
});
When several parts of a Node.js service ask for the same expensive resource at the same moment — a config fetch, a user lookup, a token refresh — each call independently fires off the underlying work. This is the thundering-herd problem: N concurrent callers cause N identical round trips, hammering a downstream API or database for a value that is identical across all of them. The fix is a promise cache: cache the in-flight Promise itself, keyed by the request, so concurrent callers share one execution and one result.
The dedupe helper implements this idea in a few lines. dedupeAsync wraps a producer function and holds a Map of key to pending promise. On the first call for a key it invokes the producer, stores the returned promise, and — crucially — attaches a .finally that deletes the entry once settled. Every subsequent call that arrives while the promise is still pending gets the same promise back instead of starting new work. Because the entry is cleared on settle, this is deduplication of concurrent calls, not a long-lived value cache; the next call after resolution starts fresh work. The keyFn lets callers derive a stable string key from arguments, and errors propagate to all sharers since a rejected promise is what gets cached and then evicted.
The UserLoader tab shows a realistic consumer. fetchUser performs a raw HTTP GET, and wrapping it with dedupeAsync keyed by user id means a burst of requests for the same id collapses into a single upstream call. The warm method demonstrates that even a Promise.all fan-out over duplicate ids issues each unique request only once.
The dedupe.test tab pins the behavior down: it counts producer invocations while firing many concurrent calls and asserts the producer ran once, that all callers resolve to the same value, and that a later call re-invokes the producer after the cache slot is freed. A key pitfall this design avoids is caching rejections forever — because eviction happens in finally, a transient failure does not poison future calls. It also stays memory-safe by never retaining settled promises. This pattern is worth reaching for whenever idempotent async work can be triggered redundantly under load.
Related snips
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
module Api
module V1
class UsersController < BaseController
def show
user = User.includes(:profile).find(params[:id])
ETags for conditional requests and caching
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
Promises and async/await patterns for asynchronous JavaScript
use crossbeam::channel::unbounded;
use std::thread;
fn main() {
let (tx, rx) = unbounded();
Crossbeam for advanced concurrent data structures
Rails.application.configure do
config.after_initialize do
Bullet.enable = true
Bullet.alert = false
Bullet.bullet_logger = true
Bullet.console = true
N+1 query detection with Bullet gem
Share this code
Here's the card — post it anywhere.