DEV Community

Cover image for How to terminate a HTTP server in Node.js?
Gajus Kuizinas
Gajus Kuizinas

Posted on

11 3 1 1 1

How to terminate a HTTP server in Node.js?

One of the most popular support questions I answer is a variation of "how to terminate a HTTP server" or "why does HTTP server not stop after calling server.close()". The reason for that is described in the documentation of server.close():

server.stop() stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally closed when all connections are ended and the server emits a 'close' event.

i.e. when you call server.close(), server stops accepting new connections, but it keeps the existing connections open indefinitely. This can result in your server hanging indefinitely due to persistent HTTP connections or because of the ongoing requests that do not produce a response. Therefore, in order to close the server, you must track creation of all connections and terminate them yourself.

The basic principle of forcefully closing a HTTP server looks like this:

import {
  createServer,
} from 'http';

const server = createServer(() => {});

server.listen();

const sockets = new Set();

server.on('connection', (socket) => {
  sockets.add(socket);

  server.once('close', () => {
    sockets.delete(socket);
  });
});

/**
 * Forcefully terminates HTTP server.
 */
const close = (callback) => {
  for (const socket of sockets) {
    socket.destroy();

    sockets.delete(socket);
  }

  server.close(callback);
};

However, abruptly terminating a HTTP server is not desirable. You want to give time for existing requests to complete (without accepting new requests) and you want to inform the client that it should not attempt to use the same connection again (in case of persist HTTP connections). All of this can be done using an abstraction such as http-terminator.

http-terminator implements the logic for tracking all connections and their termination upon a timeout. http-terminator also ensures graceful communication of the server intention to shutdown to any clients that are currently receiving response from this server.

Terminating a server using http-terminator is as simple as instantiating the service referencing the HTTP server instance and calling terminate method:

import http from 'http';
import {
  createHttpTerminator,
} from 'http-terminator';

const server = http.createServer();

const httpTerminator = createHttpTerminator({
  server,
});

await httpTerminator.terminate();

By default, http-terminator gives 1 second for the server to complete the request. This can be configured using httpResponseTimeout configuration.

Finally, it is worth mentioning that there are several alternatives that implement comparable functionality, e.g.

The main benefit of http-terminator is that:

  • it does not monkey-patch Node.js API
  • it immediately destroys all sockets without an attached HTTP request
  • it allows graceful timeout to sockets with ongoing HTTP requests
  • it properly handles HTTPS connections
  • it informs connections using keep-alive that server is shutting down by setting a connection: close header
  • it does not terminate the Node.js process

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (1)

Collapse
 
slidenerd profile image
slidenerd

How does this library work if you have a websocket server running that uses ws

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay