Back to main page Traveling Coderman

Node.js Microservice Architecture Connection pooling with Axios and agentkeepalive

If you are using plain Axios, then with each request a new connection is opened. However, the server your application is running on can only handle a limited number of connections at the same time. If no new connections can be created, then this can lead to all sort of weird errors in production. Let's avoid this and use a connection pool.

Luckily, there is an npm package agentkeepalive that implements the concept of a connection pool.

npm install agentkeepalive --save

We only need to configure axios to use this package agentkeepalive.

HTTP Agents 🔗

In a module src/http/create-http-agents.ts, we specify an HTTP agent and an HTTPS agent. The configuration depends on your production environment and requirements on the service. You might want to play around with different settings.

import Agent from "agentkeepalive";

export function createHttpAgent() {
return new Agent({
maxSockets: 100,
maxFreeSockets: 10,
timeout: 60000,
freeSocketTimeout: 30000,
});
}

export function createHttpsAgent() {
return new Agent.HttpsAgent({
maxSockets: 100,
maxFreeSockets: 10,
timeout: 60000,
freeSocketTimeout: 30000,
});
}

Connecting Axios and agentkeepalive 🔗

In the same directory src/http, we create a module configure-http.ts. It contains a function that registers the HTTP agents on the global axios object.

import axios from "axios";
import { createHttpAgent, createHttpsAgent } from "./create-http-agents";

export function configureHttp(): void {
axios.defaults.httpAgent = createHttpAgent();
axios.defaults.httpsAgent = createHttpsAgent();
}

If the function configureHttp has been called, then all requests made with the global object axios use the connection pool.

import axios from "axios";
import { config } from "../../configuration/config";

export function sendNotification(message: string): Promise<void> {
return axios.post(`${config.http.servicesUrl}/notify/notifications`, {
message,
});
}

Configuring Axios on application start 🔗

Now, we only need to make sure the function is called when the application starts. We do this as one of the first steps in the function main in the module src/main.ts.

import app from "./app";
import * as http from "http";
import { logger } from "./logger";
import { configureHttp } from "./http/configure-http";

async function main(_args: string[]) {
const port = process.env.PORT ?? 3000;
configureHttp();
const server = http.createServer(app);
server.listen(port, () => {
logger.info(`Server listening on port ${port}!`);
});
}

main(process.argv).catch((error) => {
// ...
});

// ...

Conclusion 🔗

We configured a connection pool with Axios. Every outgoing HTTP request done with the global axios object now utilizes a connection from the connection pool.

Become a GitHub sponsor to access the code of this post as a GitHub repo.