Monday, May 4, 2026

Why My NestJS App Crashes on Shared Hosting: 5 Crucial TCP Timeout Fixes You Didn't Know About

Why My NestJS App Crashes on Shared Hosting: 5 Crucial TCP Timeout Fixes You Didn't Know About

You spent hours polishing your NestJS API, pushed it to a cheap shared‑hosting plan, and boom—the server crashes right after the first request. The error logs point to “socket hang up” or “ETIMEDOUT”. If you’ve ever felt that gut‑punch of helplessness, you’re not alone. In the world of Node.js, hidden TCP time‑out settings are the silent killers of production apps.

TL;DR: Adjust the TCP keep‑alive, socket timeout, and HTTP server limits on your shared host, and your NestJS app will stay alive long enough to serve real users and keep the money flowing.

Why This Matters

Shared hosting is cheap, but it’s also a shared TCP stack. Most providers ship the default Linux kernel with aggressive timeout values to protect their resources. When a NestJS app opens a database connection or streams a large file, the kernel thinks the idle socket is “dead” and drops it after just a few seconds. The result? 502 Bad Gateway errors, endless restart loops, and a client‑facing reputation hit.

Fixing these timeouts doesn’t just make your app stable—it saves you from over‑paying for a pricey VPS, lets you scale with confidence, and keeps your API revenue stream uninterrupted.

5 TCP Timeout Fixes – Step‑by‑Step

  1. Enable TCP Keep‑Alive on the Node Process

    Node disables keep‑alive by default on outgoing sockets. Add a global setting at the top of main.ts:

    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import * as http from 'http';
    
    async function bootstrap() {
      const server = http.createServer();
      // Enable keep‑alive with a 30‑second interval
      server.keepAliveTimeout = 60_000; // 60 seconds
      server.headersTimeout = 65_000;   // a bit higher than keepAlive
      const app = await NestFactory.create(AppModule, { httpServer: server });
      await app.listen(3000);
    }
    bootstrap();
    Tip: Adjust the numbers to match your host’s net.ipv4.tcp_keepalive_time (usually 7200 s) for smoother long‑polling.
  2. Tune the Underlying Linux Kernel Parameters

    Most shared hosts let you add .htaccess directives or a small sysctl.conf snippet via cPanel “Custom PHP Settings”. Add the following to a file named custom.conf and ask support to load it:

    # Increase TCP timeout for idle connections
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_keepalive_intvl = 15
    net.ipv4.tcp_keepalive_probes = 5
    # Reduce SYN‑ACK retransmission delay
    net.ipv4.tcp_syn_retries = 5
    Warning: Not every shared host allows sysctl changes. If you hit a permission error, skip to #4 and use application‑level work‑arounds.
  3. Configure Database Drivers with Custom Timeouts

    Whether you use TypeORM, Prisma, or plain pg, set explicit connectionTimeoutMillis and idleTimeoutMillis values. Example with Prisma:

    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
      connection_timeout = 30   // seconds
      pool_timeout       = 60   // seconds
    }

    For TypeORM, it looks like this:

    createConnection({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: +process.env.DB_PORT,
      username: process.env.DB_USER,
      password: process.env.DB_PASS,
      database: process.env.DB_NAME,
      extra: {
        connectionTimeoutMillis: 30000,
        idleTimeoutMillis: 60000,
      },
    });
  4. Wrap Long‑Running Requests in a “heartbeat” Middleware

    When your API streams a large CSV or processes a big image, keep the client alive by sending periodic whitespace chunks.

    import { Injectable, NestMiddleware } from '@nestjs/common';
    import { Request, Response, NextFunction } from 'express';
    
    @Injectable()
    export class HeartbeatMiddleware implements NestMiddleware {
      use(req: Request, res: Response, next: NextFunction) {
        const interval = setInterval(() => {
          if (!res.headersSent) return;
          res.write(' '); // send a single space as a keep‑alive tick
        }, 15000); // 15 seconds
    
        res.on('finish', () => clearInterval(interval));
        res.on('close', () => clearInterval(interval));
        next();
      }
    }

    Register it globally in app.module.ts:

    import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
    import { HeartbeatMiddleware } from './heartbeat.middleware';
    
    @Module({ /* ... */ })
    export class AppModule implements NestModule {
      configure(consumer: MiddlewareConsumer) {
        consumer.apply(HeartbeatMiddleware).forRoutes('*');
      }
    }
  5. Leverage a Reverse Proxy with Higher Timeouts

    Most shared hosts ship Apache or Nginx as a front‑end. Add a custom .htaccess rule (Apache) or a nginx.conf snippet (if you have access) to bump the proxy timeout.

    Apache example:

    # .htaccess
    
      ProxyTimeout 120
      ProxyPass /api http://127.0.0.1:3000/ retry=0 timeout=120
      ProxyPassReverse /api http://127.0.0.1:3000/
    

    Nginx example (cPanel “Proxy Manager”):

    location /api/ {
      proxy_pass http://127.0.0.1:3000/;
      proxy_connect_timeout 60s;
      proxy_send_timeout 90s;
      proxy_read_timeout 90s;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
    }

Real‑World Use Case: Photo‑Processing API on Shared Hosting

John, a freelance photographer, built a NestJS microservice that receives a high‑resolution image, runs a Sharp filter, and returns the result. On his $4.99 shared plan, the API timed out after 30 seconds, leading to angry clients.

By applying the five fixes above—especially the heartbeat middleware and Nginx proxy timeout—John saw the processing time increase from 28 s to 85 s without a single 502 error. His conversion rate jumped 27% because clients finally received the edited photos.

Results & Outcome

  • Zero “socket hang up” errors in a 30‑day monitoring window.
  • CPU usage stayed under 15 % despite longer request lifetimes.
  • Monthly hosting bill stayed at $4.99—no upgrade needed.
  • Client satisfaction score rose from 3.2 → 4.8/5.

Bonus Tips for the Savvy Developer

  • Use PM2 with a graceful shutdown hook: process.on('SIGINT', () => app.close());
  • Compress large JSON responses: enable compression() middleware to reduce socket time.
  • Monitor with UptimeRobot: set a 30‑second check interval to catch timeouts before customers notice.
  • Consider a lightweight CDN: serve static assets (images, JS) from Cloudflare to free up TCP slots.

Monetize Your Stability Gains

If you’ve turned a shaky NestJS API into a rock‑solid service, why not package the knowledge?

  • Create a paid “Shared‑Host Ready NestJS Blueprint” ebook and sell it on Gumroad.
  • Offer a consultancy retainer to other freelancers battling the same timeout monster.
  • Launch a subscription‑based “API health monitor” SaaS that pings client endpoints every minute.
Ready to stop crashes and start earning? Implement the five fixes today and watch your NestJS app thrive on even the cheapest shared host.

No comments:

Post a Comment