banner image 1 banner image 2

Network I/O- The Underhood of Node.js

August 22, 2022
3 mins
blog-img 1
Rajesh krishnakumar

Is the network request from node handled by event loop or libuv? Find out with this article!

By Rajesh krishnakumar — “Go above and beyond!”

Does Node Js use libuv Thread Pool for Network I/O?

Everyone is confused that network request from node application is handled by event loop or libuv (ThreadPool).

Interviewed multiple candidates but many of them were confused about it. Let’s clear the confusion

Let’s get started

Let’s discuss a few technical words that always come across with node js

Event loop

The event loop is what allows Node. js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible. Since most modern kernels are multi-threaded, they can handle multiple operations executing in the background.


libuv is a C library originally written for Node.js to abstract non-blocking I/O operations, Lifting all the heavy jobs.

Thread Pool

Libuv assigns tasks to a pool of worker threads. However, all call-backs that occur on task completion are executed on the main thread.
By default size of UV_THREADPOOL_SIZE is 4.

Let discuss about Network I/O now

Network Call

Let us all assume that network call is blocking operation so event loop sent to thread pool do the task.

Yes, you are right but here is the catch if a request is called with the hostname then *dns.lookup()* is used so it go-to thread pool, If you called by IP or doing a lookup by yourself then dns.lookup is avoided and we can make thread pool free for another job.


Most of us call API by hostname in the node server so that means if you do >4 DNS lookups in parallel then you’re going to block the libuv thread pool.


In node js DNS.lookup() calls getaddrinfo(), a function in the system resolver library that makes blocking socket calls and cannot be integrated into the polling loop, like fs* it’s called in the thread pool. Everything else is async in DNS except DNS.lookup.

Things handled by UV thread pool

  • fs*
  • DNS(only DNS.lookup())
  • crypto (only crypto.randomBytes() and crypto.pdkdf2())
  • HTTP.get/request (if called by with a name, DNS lookup is used)
  • C++ addons

Cons of Thread Pool

Let’s say you have 100 concurrent connections everything started using thread pool it will degrade the performance, either you need to increase the thread pool or add more CPU or come out of thread pool.

Note: It doesn’t block the main thread.


Try to resolve the DNS yourself on event loop or use proxy DNS caching or calling by IP

Various networking APIs will call dns.lookup() internally to resolve host names. If that is an issue, consider resolving the hostname to an address using dns.resolve() and using the address instead of a hostname. Also, some networking APIs (such as socket.connect() and dgram.createSocket()) allow the default resolver, dns.lookup()to be replaced.

Npm package for cacheable DNS cacheable-lookup

OS level you can refer to this article

Happy coding…



Meet the team!


Rajesh krishnakumar

Reviewed By

@muthukumar k


Mridula Saravanan

We at CaratLane are solving some of the most intriguing challenges to make our mark in the relatively uncharted omnichannel jewellery industry. If you are interested in tackling such obstacles, feel free to drop your updated resume/CV to!
blog-img 2


blog-img 3
5 mins
May 17, 2023
Sharing Data Between Controllers: Best Practices S...

This article will help you to understand the diffe

By Naveen C

blog-img 3
5 mins
March 21, 2023
Understanding Auto Layout and Constraints in Swift...

This article gives you an easy way of understandin

By Ramasamy P