Lesson 12 / 25

TCP and UDP Load Balancing with the stream Module

Proxy databases, DNS and other non-HTTP protocols.

Beyond HTTP

The stream module (included in the official packages) proxies and balances TCP and UDP traffic: databases (PostgreSQL, MySQL), message brokers, DNS, syslog, game servers, or TLS passthrough to backends that terminate TLS themselves. It lives in its own top-level stream { } context, parallel to http, with upstream and server blocks similar to HTTP, but without HTTP features such as locations, headers or caching. It supports round robin, least_conn, hash and random balancing, passive health checks, proxy_timeout, connection limits and TLS termination for TCP. With ssl_preread, NGINX can read the SNI host name from a TLS ClientHello without decrypting it and route connections to different backends by host name. Because stream proxying works at layer 4, the backend sees NGINX's address unless you enable the PROXY protocol (proxy_protocol on;) and configure the backend to read it.

Balancing PostgreSQL replicas and routing TLS by SNI

Layer-4 proxying with the stream module.

stream {
    upstream pg_replicas {
        least_conn;
        server 10.0.3.11:5432 max_fails=2 fail_timeout=10s;
        server 10.0.3.12:5432 max_fails=2 fail_timeout=10s;
    }
    server {
        listen 5433;                     # read-only traffic
        proxy_pass pg_replicas;
        proxy_connect_timeout 2s;
        proxy_timeout 30m;
    }

    map $ssl_preread_server_name $tls_backend {
        api.example.com   10.0.4.10:443;
        mail.example.com  10.0.4.20:443;
        default           10.0.4.30:443;
    }
    server {
        listen 443;
        ssl_preread on;                  # read SNI without decrypting
        proxy_pass $tls_backend;
    }
}

Long-lived connections need long timeouts

Database and message-broker connections stay open for a long time. The stream proxy_timeout (default 10 minutes of inactivity) may cut idle pooled connections; align it with your clients' pool settings.

Quick check: Which NGINX context is used to load balance a PostgreSQL TCP service?

  • stream
  • http
  • location
  • events
Answer

stream — The stream module handles raw TCP and UDP proxying, outside the http context.