Course contentsShow
← Node.js
Lesson 21 of 1,9801. Node.js Foundations and Runtime InternalsFree lesson

The Close Callbacks Phase

Manage cleanup tasks for socket and descriptor closures to prevent memory leaks.

In this lesson, you will learn how Node.js gracefully cleans up resources once a socket or file descriptor is officially closed.

What is the Close Callbacks Phase?

You have already learned about the Event Loop’s many phases, such as the Poll Phase where I/O happens and the Check Phase where setImmediate runs. But what happens when an I/O resource—like a network socket—is destroyed or closed? When we call socket.destroy() or when a stream finishes, the resource isn't instantly wiped from memory. Instead, Node.js triggers a "close" event.

The Close Callbacks Phase is the final stop in the Event Loop’s tour. It is dedicated solely to executing these "close" callbacks (e.g., socket.on('close', ...)).

Why is this Phase necessary?

If you don't clean up after opening a file or a network connection, you risk a memory leak. If a program constantly opens descriptors without releasing them, the operating system will eventually hit its limits (as we discussed in our lesson on Resource Exhaustion).

The Close phase ensures that once the connection is dead, the underlying C++ handles are properly released and the memory is marked as ready for the Garbage Collector.

Consider this snippet:

const net = require('net');

const server = net.createServer((socket) => {
  socket.on('data', (data) => {
    // Once we're done, we close the socket
    socket.destroy();
  });

  socket.on('close', () => {
    console.log('Socket closed: Cleaning up resources now.');
  });
});

When socket.destroy() is called, the socket enters a pending state for closure. The Event Loop doesn't execute the 'close' logic immediately in the middle of a script. Instead, it waits until it reaches the Close Callbacks Phase. This design keeps the loop predictable: your application logic runs first, and the "housekeeping" of releasing resources happens in its own dedicated, safe window at the end of the tick.

By processing these closures in a specific phase, Node.js ensures that even if many resources close at once, they won't interrupt the critical execution flow of your active timers or pending I/O tasks.

Key Takeaway: The Close Callbacks Phase is the Event Loop’s final housekeeping stage, ensuring that resources like sockets are fully released to prevent memory leaks and handle system cleanup safely.