ARTICLE

Load Balancing on DMIT: Nginx Upstream Guide

Layer 7 load balancing with Nginx: scheduling policies, health checks, sessions and TLS offload.

When you need load balancing

When a single DMIT instance can no longer handle traffic, or the business cannot tolerate a single point of failure, requests must be distributed across multiple servers. Load balancing splits into Layer 4 (TCP/UDP — fast forwarding) and Layer 7 (HTTP/HTTPS — route by path/cookie and offload TLS). This guide builds a Layer 7 setup on DMIT using Nginx.

Architecture overview

visitors → LB (Nginx, DMIT instance A)
             ├→ app1 (DMIT instance B)
             ├→ app2 (DMIT instance C)
             └→ app3 (DMIT instance D)

The LB-to-backend link can be private or public. For cross-region deployments, combine with location selection to place backends in different regions for failover.

Nginx upstream config

# /etc/nginx/conf.d/lb.conf
upstream myapp {
    least_conn;                       # least-connections scheduling
    server 10.0.0.11:8000 weight=2 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:8000 max_fails=3 fail_timeout=30s;
    server 10.0.0.13:8000 backup;     # standby node
    keepalive 32;
}

server {
    listen 443 ssl;
    server_name example.com;
    # ssl_certificate ...;

    location / {
        proxy_pass http://myapp;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_next_upstream error timeout http_502;   # automatic failover
    }
}

Choosing a scheduling policy

PolicyBehaviourFits
round-robinRotate evenly (default)Similar backend capacity
least_connPick the node with fewest active connectionsHighly variable request durations
ip_hashPin one IP to one nodeSimple session stickiness without shared state
weightDistribute by weightUneven backend specs

Health checks

Open-source Nginx uses passive checks: max_fails + fail_timeout temporarily remove a node after repeated failures. For active probing, add a lightweight health endpoint plus a cron job:

# backend serves /healthz returning 200
# probe every minute from the LB and alert
*/1 * * * * curl -sf http://10.0.0.11:8000/healthz || echo "app1 down" | mail -s "LB alert" ops@example.com

Full monitoring/alerting in Prometheus + Grafana Monitoring.

Sessions and shared state

  • Prefer externalising state: sessions in Redis, files in object storage — any node can serve any request
  • If state cannot move, use ip_hash or app-level sticky cookies as a stopgap
  • Keep databases single-writer; read scaling in Database Optimisation

TLS offload and end-to-end HTTPS

  • Certificates only on the LB, HTTP to private backends — simple config, centralised renewal (see HTTPS Setup)
  • Encrypt links crossing the public internet: backends get certs too, LB uses proxy_pass https:// with verification
  • Pass X-Forwarded-Proto so apps know the original scheme and avoid redirect loops

Common issues

Bursts of 502?

Check each backend's health and the LB error log (tail -f /var/log/nginx/error.log); usually a dead backend process or missing HTTP/1.1 keepalive settings. See Troubleshooting Guide.

Users losing login state?

Sessions are not shared across nodes. Move sessions to Redis, or switch to ip_hash temporarily.

Real visitor IP missing?

Ensure the LB sets X-Real-IP/X-Forwarded-For and the app trusts those headers; with a CDN in front, also see CDN Setup.

Related articles

Prometheus + Grafana Monitoring, Performance Tuning, CI/CD Deploy.

Data checked: 2026-08-18. Nginx directives follow official documentation.

NEXT STEP

Ready to pick your DMIT plan?

Filter the official snapshot by budget and network, or check live stock at DMIT.

Disclosure: purchases through this link may earn the referrer a commission at no extra cost to you.