Mastering Nginx ip_hash for Session Affinity and Its Common Pitfalls

This article explains how Nginx's ip_hash directive implements session affinity by routing all requests from the same client IP to a single backend server, demonstrates configuration examples, analyzes behavior when servers go down, and discusses the method's limitations such as load imbalance and dynamic IP issues.

Architect
Architect
Architect
Mastering Nginx ip_hash for Session Affinity and Its Common Pitfalls

Background

A recent project required that all requests from the same client be sent to the same backend server to keep session data consistent.

All requests from the same client must be routed to the same backend server to ensure session state consistency.

Session Affinity

Session affinity (also called session persistence or stickiness) is a load‑balancing strategy that routes every request from a given client to the same backend server, typically using the client’s IP address or a cookie.

The interaction diagram is shown below:

Implementation with Nginx

Nginx can hash the client IP address and map the hash value to a specific upstream server, thereby achieving session affinity.

Three clients with distinct fixed IPs send requests to Nginx; Nginx hashes each IP, computes a hash value, and maps it to a particular upstream server.

The server generates a session ID with an expiration time and returns it to the client. Subsequent requests carry the session ID, ensuring they are routed to the same server, which validates the session ID’s existence and validity.

ip_hash Directive

The ip_hash directive tells Nginx to use the client IP as the hashing key.

Syntax: ip_hash;
Default:
Context: upstream

Official description (Nginx documentation):

Specifies that a group should use a load balancing method where requests are distributed between servers based on client IP addresses. The first three octets of the client IPv4 address, or the entire IPv6 address, are used as a hashing key. The method ensures that requests from the same client will always be passed to the same server except when this server is unavailable. In the latter case client requests will be passed to another server. Most probably, it will always be the same server as well.

Notes from the documentation:

IPv6 support starts from version 1.3.2 and 1.2.2.

Before versions 1.3.1 and 1.2.2, ip_hash cannot be used together with weight configuration.

To temporarily remove a server from the pool, mark it with the down parameter.

Configuration Example

Below is a typical upstream block using ip_hash:

upstream backend {
    ip_hash;

    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

Explanation of each line: ip_hash: tells Nginx to hash the client IP and consistently route requests from the same IP to the same backend. server: lists the backend servers. In the example there are four servers: backend1.example.com, backend2.example.com, backend3.example.com, and backend4.example.com. backend3.example.com down: the down keyword marks this server as temporarily unavailable, so it will not accept new connections. This is useful for maintenance or fault isolation.

With this configuration, Nginx routes requests based on the client IP, guaranteeing that all requests from the same client reach the same backend, thus preserving session state.

GitHub Issue Illustration

A GitHub gist raised the question of what happens when a server marked down comes back up:

When an IP is hashed to server A and A is marked down, does the IP get reassigned to another server (e.g., B)? If A later recovers, does the IP go back to A?

Test results:

After marking server A down, requests from 192.168.1.10 were routed to server B.

After removing the down flag, the same IP was routed back to server A.

Pitfalls of ip_hash

Not suitable for uneven load: ip_hash does not consider server load, so a heavily used server may become a bottleneck while others stay idle.

Limited load‑balancing capabilities: It only uses client IP and ignores server health metrics; more advanced modules like least_conn or the full ngx_http_upstream_module may be required for complex scenarios.

Potential resource waste: A high‑frequency client can overload a single backend, leaving other backends underutilized.

Dynamic IP issues: Clients with DHCP‑assigned or frequently changing IPs may lose session affinity, causing state loss.

Session state maintenance: Using ip_hash often requires additional mechanisms to store session data, increasing system complexity compared to stateless load balancing.

Conclusion

ip_hash is effective for scenarios that require strict session affinity, but it brings drawbacks such as load imbalance, limited configurability, and challenges with dynamic IPs. Evaluate the trade‑offs before adopting it as the sole load‑balancing method.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendperformanceload balancingConfigurationNginxIP Hashsession-affinity
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.