typescript 78 lines · 3 tabs

HTTP keep-alive agent for outbound calls

Shared by codesnips Jan 2026
3 tabs
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';

const shared = {
  keepAlive: true,
  keepAliveMsecs: 1_000,
  maxSockets: 64,
  maxFreeSockets: 16,
  timeout: 30_000,
  scheduling: 'lifo' as const,
};

export const httpAgent = new HttpAgent(shared);
export const httpsAgent = new HttpsAgent(shared);

export function agentStats() {
  return {
    http: {
      free: Object.values(httpAgent.freeSockets).flat().length,
      active: Object.values(httpAgent.sockets).flat().length,
    },
    https: {
      free: Object.values(httpsAgent.freeSockets).flat().length,
      active: Object.values(httpsAgent.sockets).flat().length,
    },
  };
}
3 files · typescript Explain with highlit

Every outbound HTTP call from a Node service can pay a hidden tax: opening a fresh TCP connection (and a TLS handshake for HTTPS) before a single byte of the request is sent. Under load this adds latency and burns file descriptors and ephemeral ports. The fix is connection reuse via keep-alive http.Agent/https.Agent instances that pool sockets across requests, and this snippet shows how to wire that pooling into a shared client.

In agents.ts, two singleton agents are created with keepAlive: true and a keepAliveMsecs interval so the OS sends TCP keep-alive probes on idle sockets. maxSockets caps concurrent connections per host so a burst cannot exhaust upstream capacity, while maxFreeSockets bounds how many idle sockets are retained for reuse. scheduling: 'lifo' is chosen deliberately: last-in-first-out keeps a small hot set of sockets warm and lets the rest idle out via timeout, which plays better with load balancers that reap idle connections than round-robin would. Exporting these as module-level singletons is essential — creating an agent per request defeats the entire purpose, since each new agent owns its own pool.

httpClient.ts builds an axios instance that hands the correct agent to each protocol through httpAgent and httpsAgent. A response interceptor reads res.request.reusedSocket to expose whether a call reused a pooled connection, which is invaluable when verifying the pool is actually working in production. The shutdownAgents helper calls destroy() on both agents so in-flight sockets are closed cleanly during graceful shutdown, avoiding leaked connections when the process exits.

gracefulShutdown.ts ties it together, draining the HTTP server and then tearing down the agent pools on SIGTERM. The main trade-off of keep-alive is stale sockets: an upstream or proxy may silently close a connection that the client still believes is open, surfacing as ECONNRESET. Bounding idle lifetime with timeout and retrying idempotent requests on that specific error mitigates it. This pattern is worth reaching for whenever a service makes repeated calls to the same handful of hosts.


Related snips

typescript
export interface RetryOptions {
  retries: number;
  baseMs: number;
  maxMs: number;
  signal?: AbortSignal;
  onRetry?: (attempt: number, delay: number, err: unknown) => void;

Exponential backoff with jitter for retries

typescript reliability retry
by codesnips 2 tabs
ruby
require "csv"

class PeopleCsvStream
  include Enumerable

  HEADERS = %w[id full_name email signed_up_at plan].freeze

Resilient CSV Export as a Streamed Response

rails performance streaming
by codesnips 3 tabs
ruby
Rails.application.configure do
  config.after_initialize do
    Bullet.enable = true
    Bullet.alert = false
    Bullet.bullet_logger = true
    Bullet.console = true

N+1 query detection with Bullet gem

rails performance activerecord
by Alex Kumar 2 tabs
ruby
json.array! @posts do |post|
  json.cache! ['v1', post], expires_in: 1.hour do
    json.id post.id
    json.title post.title
    json.excerpt post.excerpt
    json.published_at post.published_at

Fragment caching for expensive JSON serialization

rails caching performance
by Alex Kumar 1 tab
typescript
import axios, { AxiosError } from 'axios'
import { v4 as uuidv4 } from 'uuid'

const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1',
  timeout: 15000,

Axios API client with interceptors

react axios api
by Maya Patel 1 tab
typescript
import { create } from 'zustand'
import { persist } from 'zustand/middleware'

interface FilterState {
  search: string
  category: string | null

Zustand for lightweight state management

react zustand state-management
by Maya Patel 2 tabs

Share this code

Here's the card — post it anywhere.

HTTP keep-alive agent for outbound calls — share card
Link copied