how to make synchronous http calls within async.each in nodejs
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Node.js, the right answer is usually not to make synchronous HTTP calls at all. Network I O is inherently asynchronous in the platform, and trying to force it into a blocking model defeats the event loop. If you need one request at a time inside async.each, use a serial iterator such as async.eachSeries or rewrite the flow with async and await.
Why Synchronous HTTP Is the Wrong Goal
Blocking the event loop means the whole process stops handling other work while one request is in flight. That is almost always a bad tradeoff for a server or worker process.
So there are two distinct goals that developers often confuse:
- synchronous API, meaning the code looks sequential
- synchronous execution, meaning the process is truly blocked
Node supports the first through callbacks, promises, and async / await. It should usually avoid the second.
Use async.eachSeries for Sequential Requests
If you are already using the async library and want each HTTP request to complete before the next begins, switch from each to eachSeries.
This preserves sequential behavior without turning HTTP itself into a blocking operation.
Prefer async and await in Modern Code
For modern Node.js code, a plain loop with await is usually easier to read than callback-driven async.each helpers.
This code is sequential in structure, but still asynchronous in execution. That is exactly what most Node applications want.
Limit Concurrency Instead of Forcing Sync
Sometimes the real need is not "fully synchronous", but "do not overwhelm the remote API". In that case, limiting concurrency is better than making requests strictly one by one.
Use async.eachLimit, a queue, or a small promise pool so the process stays efficient while respecting rate limits.
That usually gives better throughput and still protects external systems.
Respect Remote Service Limits
If these requests go to a third-party API, sequential execution may not be the only safe option. Often the better design is a small concurrency limit plus retry and backoff logic so your process stays efficient without violating rate limits. That usually solves the original concern better than forcing a blocking request model.
Common Pitfalls
- Trying to block the Node event loop for network requests.
- Using
async.eachwhen the workflow actually requires serial ordering. - Mixing callbacks, promises, and
awaitin the same control path without a clear reason. - Solving rate-limit problems by forcing full serialization instead of using bounded concurrency.
- Treating code that looks sequential as if it must also block the process.
Summary
- In Node.js, truly synchronous HTTP calls are usually the wrong goal.
- If you need sequential behavior with the
asynclibrary, useeachSeriesinstead ofeach. - In modern code,
asyncandawaitwith a normal loop is often the clearest solution. - For throughput and external API safety, bounded concurrency is often better than strict serialization.
- Keep the event loop non-blocking unless you have an unusually strong reason not to.

