# Session Persistence Type of document: How-to guide Product: NGINX Gateway Fabric --- Learn how to configure session persistence using NGINX Gateway Fabric. ## Overview In this guide, you’ll learn how to configure session persistence for your application. Session persistence ensures that multiple requests from the same client are consistently routed to the same backend Pod. This is useful when your application maintains in-memory state (for example, shopping carts or user sessions). NGINX Gateway Fabric supports configuring session persistence via `UpstreamSettingsPolicy` resource or directly on `HTTPRoute` and `GRPCRoute` resources. For NGINX OSS users, using the `ip_hash` load-balancing method provides basic session affinity by routing requests from the same client IP to the same backend Pod. For NGINX Plus users, cookie-based session persistence can be configured using the `sessionPersistence` field in a Route. In this guide, you will deploy three applications: - An application configured with `ip_hash` load-balancing method. - An application configured with cookie–based session persistence (if you have access to NGINX Plus). - A regular application with default load-balancing. These applications will showcase the benefits of session persistence for stateful workloads. The NGINX directives discussed in this guide are: - [`ip_hash`](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash) - [`sticky cookie`](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#sticky) ## Note **Note:** Cookie-based `SessionPersistence` is only available for [NGINX Plus](/ngf/install/nginx-plus.md) users, with alternatives provided for NGINX OSS users. Session Persistence is a Gateway API field from the experimental release channel and is subject to change. ## Before you begin [Install](/ngf/install/nginx-plus.md) NGINX Gateway Fabric with **NGINX Plus** and experimental features enabled if you want to use cookie-based `sessionPersistence`. If you plan to use the `ip_hash` load-balancing method for session affinity instead, installing NGINX Gateway Fabric with **NGINX OSS** is sufficient. To use Gateway API experimental resources, the Gateway API resources from the experimental channel must be installed before deploying NGINX Gateway Fabric. Additionally, NGINX Gateway Fabric must have experimental features enabled. **Note:** As noted in the [Gateway API documentation](https://gateway-api.sigs.k8s.io/guides/#install-experimental-channel), future releases of the Gateway API can include breaking changes to experimental resources and fields. To install the Gateway API resources from the experimental channel, run the following: ```shell kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/experimental?ref=v" | kubectl apply -f - ``` **Note:** If you plan to use the `edge` version of NGINX Gateway Fabric, you can replace the version in `ref` with `main`, for example `ref=main`. To enable experimental features on NGINX Gateway Fabric: Using Helm: Set `nginxGateway.gwAPIExperimentalFeatures.enable` to true. An example can be found in the [Installation with Helm](/ngf/install/helm.md#custom-installation-options) guide. Using Kubernetes manifests: Add the `--gateway-api-experimental-features` command-line flag to the deployment manifest args. An example can be found in the [Installation with Kubernetes manifests](/ngf/install/manifests.md#3-deploy-nginx-gateway-fabric) guide. ## Setup Create the `coffee`, `tea` and `latte` applications: ```yaml kubectl apply -f - < pod/coffee-5b9c74f9d9-7gfwn 1/1 Running 0 3h19m 10.244.0.94 kind-control-plane pod/latte-d5f64f67f-9t2j5 1/1 Running 0 3h19m 10.244.0.96 kind-control-plane pod/latte-d5f64f67f-drwc6 1/1 Running 0 3h19m 10.244.0.98 kind-control-plane pod/tea-859766c68c-cnb8n 1/1 Running 0 3h19m 10.244.0.93 kind-control-plane pod/tea-859766c68c-kttkb 1/1 Running 0 3h19m 10.244.0.97 kind-control-plane NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/coffee ClusterIP 10.96.169.1 80/TCP 3h19m app=coffee service/latte ClusterIP 10.96.42.39 80/TCP 3h19m app=latte service/tea ClusterIP 10.96.81.103 80/TCP 3h19m app=tea ``` Create a Gateway: ```yaml kubectl apply -f - < ``` **Note:** In a production environment, you should have a DNS record for the external IP address that is exposed, and it should refer to the hostname that the gateway will forward for. ## Session Persistence Methods ## Choosing the right session persistence method for your environment The choice between `ip_hash` and cookie-based session persistence depends on your use case. The `ip_hash` load-balancing method provides basic IP-based affinity: as long as NGINX sees the real client IP and not many users share that IP, requests from the same client will usually go to the same upstream Pod. However, there are important limitations: - **Shared IPs:** When there is a load balancer or proxy in front of NGINX that does not preserve the real client IP, or when many users appear to come from a single IP address (for example, corporate NAT or VPNs), `ip_hash` operates on the shared IP rather than on individual users. This means many different users behind the same IP are all routed to the same upstream Pod, so you do not get true per-user stickiness. - **Changing IPs:** If a user’s apparent IP changes over time (for example, when a load balancer or NAT pool uses multiple egress addresses), that user can be rehashed to a different upstream Pod and lose stickiness. Cookie-based session persistence with `sticky cookie` provides stronger, per-user stickiness. NGINX issues a session cookie, and all subsequent requests that present that cookie are routed to the same upstream Pod, regardless of changes in client IP or intermediate proxies. This is generally preferable for stateful, user-centric applications, while `ip_hash` can be a simpler option in NGINX OSS deployments where NGINX sees distinct, stable client IP addresses. ### Session Persistence with NGINX OSS In this section, you’ll configure a basic `coffee` HTTPRoute that routes traffic to the `coffee` Service. You’ll then attach an `UpstreamSettingsPolicy` to change the load-balancing method for that upstream to showcase session affinity behavior. NGINX hashes the client IP to select an upstream server, so requests from the same IP are routed to the same upstream as long as it is available. Session affinity quality with `ip_hash` depends on NGINX seeing the real client IP. In environments with external load balancers or proxies, operators must ensure appropriate `real_ip_header/set_real_ip_from` configuration so that `$remote_addr` reflects the end-user address otherwise, stickiness will be determined by the address of the front-end proxy rather than the actual client. To create an HTTPRoute for the `coffee` service, copy and paste the following into your terminal: ```yaml kubectl apply -f - <