Skip to content

typescript.unbounded_concurrency

Scalability High Causes Production Outages

Detects Promise.all() with unbounded arrays.

Unbounded concurrency exhausts resources:

  • Memory exhaustion — All promises held in memory
  • Connection limits — Hundreds of simultaneous requests
  • Rate limiting — APIs reject excessive requests
  • Downstream collapse — Overwhelming databases/services
// ❌ Before
await Promise.all(items.map(item => process(item)));

10,000 items = 10,000 simultaneous operations.

// ✅ After
import pLimit from 'p-limit';
const limit = pLimit(10);
await Promise.all(items.map(item => limit(() => process(item))));

Now maximum 10 concurrent operations.

  • Promise.all() with mapped arrays
  • Unbounded array of promises
  • Missing concurrency limits

Unfault can add p-limit based concurrency control when the Promise.all pattern is recognized.

// p-limit
import pLimit from 'p-limit';
const limit = pLimit(10);
const results = await Promise.all(urls.map(url => limit(() => fetch(url))));
// p-map (higher level)
import pMap from 'p-map';
const results = await pMap(urls, url => fetch(url), { concurrency: 10 });
// Manual batching
async function batchProcess<T, R>(
items: T[],
fn: (item: T) => Promise<R>,
batchSize: number
): Promise<R[]> {
const results: R[] = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchResults = await Promise.all(batch.map(fn));
results.push(...batchResults);
}
return results;
}