JavaScript
Concurrency control
Learn to limit how many operations run at once and process in batches.
Concurrency control
You have thousands of async tasks (say 1000 API calls). Starting them all at once overwhelms the server, hits rate limits or exhausts connections. Concurrency control lets only N jobs run at a time; the rest wait their turn.
// 1000 calls at once = bad idea
await Promise.all(urls.map(fetch));
// groups of 2 = safe
This keeps throughput high while keeping server load predictable.
The pool pattern
A common pattern for concurrency is the pool: N jobs run at once; when one finishes, the next starts. This builds a queue-and-worker flow.
async function pool(tasks, limit) {
const results = [];
for (let i = 0; i < tasks.length; i = i + limit) {
const batch = tasks.slice(i, i + limit);
const out = await Promise.all(batch.map(t => t()));
results.push(...out);
}
return results;
}
This simple version splits tasks into groups of size limit and runs each group in turn.
Exercise Batch processing function
Write an async function called runBatch(tasks, limit). Create an empty array named results. Split the tasks array into groups of size limit: use a for loop that increments i by limit and takes a group with tasks.slice(i, i + limit). Run each group together with Promise.all (via batch.map(t => t())); push the results with results.push(...out). Finally, return results. For testing, create tasks from the array [1, 2, 3, 4, 5] that double each number, then call runBatch(tasks, 2) and log the result with console.log.
Show example solution
async function runBatch(tasks, limit) {
const results = [];
for (let i = 0; i < tasks.length; i = i + limit) {
const batch = tasks.slice(i, i + limit);
const out = await Promise.all(batch.map(t => t()));
results.push(...out);
}
return results;
}
const tasks = [1, 2, 3, 4, 5].map(n => () => Promise.resolve(n * 2));
runBatch(tasks, 2).then(r => console.log(r));
Test yourself
-
You have 1000 API calls. Why is launching them all at once with Promise.all a bad idea?
- The server may hit rate limits or run out of connections
- Promise.all runs slowly
- Promise.all does not support more than 1000 calls
- JavaScript limits this automatically
Show answer
The server may hit rate limits or run out of connections — Correct! Too many concurrent requests can hit rate limits or exhaust connections.
-
Set the concurrency limit
const LIMIT = ____;
async function pool(tasks) {
const results = [];
for (const task of tasks.slice(0, LIMIT)) {
results.push(await task());
}
return results;
}
Show answer
const LIMIT = 3;
async function pool(tasks) {
const results = [];
for (const task of tasks.slice(0, LIMIT)) {
results.push(await task());
}
return results;
}
-
Match the concurrency concepts
- batch
- small groups
- pool
- N jobs at once
- rate limit
- speed cap
- queue
- next job
Next lesson: Summary - Async patterns