# Nginx Configuration Required for Sub2API Sticky Sessions

> Learn the Nginx configuration required for Sub2API sticky sessions. Use the sticky directive and sub2api_session cookie to route clients to the same backend instance.

- Repository: [Wesley Liddick/sub2api](https://github.com/Wei-Shaw/sub2api)
- Tags: how-to-guide
- Published: 2026-08-23

---

**Sub2API requires Nginx to configure sticky sessions using the `sticky` directive in the upstream block, which routes clients to the same backend instance via a `sub2api_session` cookie that preserves the `session_hash` across requests.**

The Wei-Shaw/sub2API repository implements stateful session handling that relies on consistent client-to-server routing to maintain continuity. To ensure the **`session_hash`** (also referenced as **`previous_response_id`**) remains bound to a specific backend worker, the reverse proxy must issue a persistent cookie and honor it for subsequent requests. According to the deployment documentation in [`deploy/README.md`](https://github.com/Wei-Shaw/sub2api/blob/main/deploy/README.md), this requires enabling the sticky session module in Nginx and configuring specific upstream and proxy settings.

## How Sub2API Sticky Sessions Work

### The session_hash Cookie Mechanism

Sub2API tracks user sessions by emitting a **`session_hash`** cookie that identifies the specific backend instance handling the request. When the API runs behind a load balancer, subsequent requests must reach the same worker to access cached session data and consistent rate-limiting states. The frontend type definitions in [`frontend/src/types/index.ts`](https://github.com/Wei-Shaw/sub2api/blob/main/frontend/src/types/index.ts) reference this as `sticky_score` and related session fields, while the backend logic in [`backend/internal/web/static_cache.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/web/static_cache.go) and [`backend/internal/repository/usage_log_repo.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/repository/usage_log_repo.go) depends on this hash remaining stable for accurate usage logging and cache retrieval.

Without sticky session configuration, Nginx distributes requests round-robin across workers, causing session state fragmentation and potential rate-limiting errors.

## Required Nginx Configuration

The recommended setup uses the **`sticky`** directive available in the open-source `nginx-upstream-sticky-module` or the commercial NGINX Plus distribution. This creates an upstream block that assigns each client a cookie-based routing identifier.

```nginx

# -------------------------------------------------

# Upstream definition – enables sticky routing

# -------------------------------------------------

upstream sub2api {
    # List each Sub2API instance (replace with your host/port)

    server 127.0.0.1:8000;
    server 127.0.0.1:8001;

    # Create a sticky cookie that lasts 1 hour

    sticky cookie sub2api_session expires=1h path=/;
}

# -------------------------------------------------

# Server block – public entry point

# -------------------------------------------------

server {
    listen 80;
    server_name api.example.com;   # <-- set your domain

    # -------------------------------------------------

    # Proxy all API paths to the upstream

    # -------------------------------------------------

    location / {
        proxy_pass http://sub2api;
        proxy_http_version 1.1;

        # Preserve original request headers

        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_set_header X-Forwarded-Proto $scheme;

        # Forward the sticky cookie (handled automatically)

        proxy_set_header Cookie $http_cookie;

        # Optional security tweaks

        proxy_cookie_path / "/; HttpOnly; Secure";
        client_max_body_size 10m;   # adjust if needed

    }

    # -------------------------------------------------

    # Health-check endpoint (optional)

    # -------------------------------------------------

    location /healthz {
        proxy_pass http://sub2api/healthz;
        proxy_set_header Host $host;
    }
}

```

## Key Configuration Components

Understanding each directive ensures reliable session persistence in production environments.

**Upstream Block with Sticky Directive**

The `upstream sub2api` block declares the pool of backend processes. The **`sticky cookie sub2api_session`** directive tells Nginx to generate a routing cookie named `sub2api_session` with a one-hour expiration. As implemented in Wei-Shaw/sub2api, this cookie guarantees that requests bearing this identifier route to the same worker where the `session_hash` originated.

**Proxy Header Preservation**

The `proxy_set_header` directives ensure Sub2API receives accurate client metadata for rate-limiting and auditing. Specifically, **`proxy_set_header Cookie $http_cookie`** forwards the `sub2api_session` cookie so the backend can validate the session continuity. The [`backend/internal/repository/usage_log_repo.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/repository/usage_log_repo.go) file relies on these headers to attribute requests correctly to individual sessions.

**Payload Size Configuration**

The **`client_max_body_size 10m`** directive adjusts maximum request payload limits. This is critical if Sub2API handles image uploads or large JSON payloads that exceed Nginx default limits.

## Source Code Integration

Several files in the Wei-Shaw/sub2api repository interact with the sticky session mechanism:

- **[`backend/internal/web/static_cache.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/web/static_cache.go)** – Handles HTTP caching headers and works in conjunction with sticky-session routing to ensure cached responses align with the correct session hash.

- **[`backend/internal/repository/usage_log_repo.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/repository/usage_log_repo.go)** – Persists per-session usage logs that depend on stable `session_hash` values provided by the sticky session configuration.

- **[`frontend/src/types/index.ts`](https://github.com/Wei-Shaw/sub2api/blob/main/frontend/src/types/index.ts)** – Defines TypeScript interfaces for `sticky_score` and session-related fields that the frontend expects to remain consistent throughout the cookie lifetime.

- **[`deploy/EDGE_SECURITY.md`](https://github.com/Wei-Shaw/sub2api/blob/main/deploy/EDGE_SECURITY.md)** – Documents edge-level security considerations, including recommendations for securing the sticky session cookie with HttpOnly and Secure flags.

## Security Considerations

When terminating TLS at Nginx, apply strict cookie security parameters to prevent session hijacking. The **`proxy_cookie_path / "/; HttpOnly; Secure"`** directive marks the `sub2api_session` cookie inaccessible to JavaScript and restricts transmission to HTTPS connections only. As noted in [`deploy/EDGE_SECURITY.md`](https://github.com/Wei-Shaw/sub2api/blob/main/deploy/EDGE_SECURITY.md), these measures protect the session identifier from XSS attacks and man-in-the-middle interception.

## Summary

- **Sticky sessions** are mandatory for Sub2API to maintain consistent `session_hash` routing across multiple backend workers.

- Configure the **`sticky cookie`** directive in the Nginx upstream block to generate the `sub2api_session` routing identifier.

- Preserve client metadata using **`proxy_set_header`** directives so [`backend/internal/repository/usage_log_repo.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/repository/usage_log_repo.go) can accurately track per-session metrics.

- Secure the configuration using **`proxy_cookie_path`** with HttpOnly and Secure flags to protect session integrity at the edge.

- Reference the official deployment guide in **[`deploy/README.md`](https://github.com/Wei-Shaw/sub2api/blob/main/deploy/README.md)** for complete implementation details specific to the Wei-Shaw/sub2api architecture.

## Frequently Asked Questions

### Does Sub2API require the commercial NGINX Plus version for sticky sessions?

No, Sub2API works with the open-source **`nginx-upstream-sticky-module`** or NGINX Plus. The configuration syntax remains identical using the `sticky cookie` directive. Ensure your Nginx build includes the sticky module before deploying the configuration from [`deploy/README.md`](https://github.com/Wei-Shaw/sub2api/blob/main/deploy/README.md).

### What happens if the sticky session cookie expires?

When the `sub2api_session` cookie expires, Nginx routes the next request to any available backend worker using standard load-balancing algorithms. Sub2API will generate a new `session_hash` for that worker, potentially resetting rate limits and cache states for that client session.

### Can I use IP hash instead of cookie-based sticky sessions?

While **`ip_hash`** provides an alternative load-balancing method, Sub2API specifically recommends cookie-based sticky sessions because they survive network address translation (NAT) and mobile network IP changes. The `session_hash` mechanism in [`backend/internal/web/static_cache.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/web/static_cache.go) expects the cookie-based routing defined in the upstream configuration.

### How do I verify that sticky sessions are working correctly?

Monitor the `sub2api_session` cookie in browser developer tools or curl responses. Each request should present the same cookie value, and [`backend/internal/repository/usage_log_repo.go`](https://github.com/Wei-Shaw/sub2api/blob/main/backend/internal/repository/usage_log_repo.go) should show consistent session attribution in logs. Additionally, check that sequential requests hit the same backend instance by examining your application logs for matching worker process IDs.