typescript.unbounded_concurrency
Scalability
High
Causes Production Outages
Detects Promise.all() with unbounded arrays.
Why It Matters
Section titled “Why It Matters”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
Example
Section titled “Example”// ❌ Beforeawait Promise.all(items.map(item => process(item)));10,000 items = 10,000 simultaneous operations.
// ✅ Afterimport pLimit from 'p-limit';
const limit = pLimit(10);await Promise.all(items.map(item => limit(() => process(item))));Now maximum 10 concurrent operations.
What Unfault Detects
Section titled “What Unfault Detects”Promise.all()with mapped arrays- Unbounded array of promises
- Missing concurrency limits
Auto-Fix
Section titled “Auto-Fix”Unfault can add p-limit based concurrency control when the Promise.all pattern is recognized.
Concurrency Libraries
Section titled “Concurrency Libraries”// p-limitimport 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 batchingasync 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;}