Sticky vs Rotating Sessions: When the IP Must Not Change

When to reuse a session ID so every request in a task leaves from one exit, how long a pin lasts on each product, and what to do when it ends.

Reuse a session ID whenever the target remembers something about your visit between one request and the next: a login, a cart, a multi-step form, a paginated result set. Rotate (send the bare credential) when each request stands alone: price checks, availability lookups, single-page fetches. A rotating gateway picks a new exit per connection by default; a session ID in the username holds one exit for a task instead.

How to keep the same IP for a task

On the residential gateway, add a session segment to the username:

curl -x "http://USERNAME-session-task81f3:PASSWORD@gw-residential.node4.io:8082" https://api.ipify.org
curl -x "http://USERNAME-session-task81f3:PASSWORD@gw-residential.node4.io:8082" https://api.ipify.org

Both commands print the same address. The id (task81f3 here) is a string you invent: letters and digits, up to 32 characters. Requests carrying the same id resolve to the same exit while the session lives; a different id draws a different exit. There is nothing to create or tear down; the id is the handle.

The same segment works on Rotating Datacenter and Rotating Unmetered, in the same position with the same grammar. What differs is how long the pin lasts:

Two more properties. Session ids are private to your account: they are hashed with a per-account salt before use, so your task81f3 and another customer's task81f3 are unrelated. And the segment composes with location: USERNAME-country-gb-session-task81f3 holds one British exit, with the location segments narrowing the candidates and the session pinning the choice. The full grammar is in country and city targeting.

What breaks when the exit changes mid-task

If the target ties state to the address the session arrived from, a mid-task change of exit can end that state. The proxy returns no error and every request succeeds at the HTTP layer; the damage shows up in the application flow, often several steps later.

Logins. Many sites bind an authenticated session to context that includes the originating address. Strictness varies: some tolerate drift within a country, many force re-authentication on any change, and a country change mid-session usually does. A worker that logs in through one exit and continues through another may get a login page, or have the account flagged, since a mid-session jump to a distant network is what a stolen session cookie looks like.

Carts and checkouts. A purchase is a multi-request conversation, and payment risk scoring treats a network hop partway through it as a strong signal. The visible result is an emptied cart, a voided session, or a declined order with no reason given.

Multi-step forms. The server holds partial progress keyed to your session, and a familiar cookie arriving from an unfamiliar address commonly resets the flow or rejects the submission.

Paginated result sets. Some search implementations bind a result cursor to session context. Request page seven through a fresh exit and you may get a fresh query context instead: page one again, or the same items re-sorted. Every request succeeded, but the output has duplicated early pages and a missing tail.

Recognizing it

Because the loss happens in the application rather than the transport, you diagnose it from behavior:

To confirm, log which address each request left from (a periodic check against https://api.ipify.org through the same client works) and see whether failures line up with changes. The decisive test is to run the identical flow through an address that cannot change (a static datacenter proxy); if it completes cleanly, mid-flow rotation was the cause.

How long a session should last

Scope the session to the task, not the day: generate a fresh id when a task starts, use it for every request in that task, and drop it when the task ends. A checkout needs minutes; scraping one account's dashboard might need fifteen.

One long-lived id shared by everything works less well, for three reasons. Residential exits are consumer devices that come and go, so the longer you hold one, the more likely it changes underneath you mid-task. Funnelling a whole day's traffic through one held exit rebuilds the single-address bottleneck a pool exists to remove, and that address starts attracting the volume-based attention described in why is my IP getting blocked. And tasks become entangled: whatever reputation one task earns the exit, every other task inherits.

Sessions also end on their own: the rotating window expires, an idle residential id stops resolving, or the exit disappears. Treat every session as expiring and design for it.

One worker, one session

Give every session id exactly one owner. Two workers sharing an id interleave two conversations through one exit: their target-side sessions can collide (two carts under one identity is its own fraud signal), their combined request rate lands on one address, and neither can reason about what "its" exit has already done.

In a job system, derive the id from the job: job4182 as the session id means a retry reuses the same identity and continues the same conversation. The exception is a retry whose failure was the exit itself (the address went dead or was blocked mid-task): salt the id with the attempt number, job4182a2, so each attempt is a fresh identity.

Headless-browser fleets follow the same rule with one addition: give each browser context its own session id and its own cookie state, so the network identity and the browser identity change together. Puppeteer and Playwright proxies covers wiring credentials into browser contexts.

When a session expires mid-task

Two things happen at once: the id begins resolving to a new exit, and the target, seeing the new address, drops or challenges the state it was holding for you. From inside the worker this looks the same as the failure signature above, so one handler covers both.

That handler should restart rather than resume. Re-entering a multi-step flow at step four with a new network identity is the pattern targets are built to distrust, and the server-side half of your progress is gone anyway. The robust loop: detect the signature (login redirect, token mismatch, cart mismatch), abandon the session id, mint a fresh one, and rerun the task from its first step, including logging in again if needed.

This is also the argument for short tasks. A restart costs little when a task is three minutes of work and hurts when it throws away three hours. Make tasks small and rerunnable (idempotent writes, or a cheap "already done?" check at the top) and session expiry becomes noise rather than an incident.

When to rotate instead

Where no state exists, rotation is the better default: stickiness protects nothing and only concentrates volume onto exits that would otherwise stay fresh. How IP rotation works covers the mechanisms and how to choose a rate.

Most pipelines contain both halves, and the mode is chosen per request by the username you send. Rotate the discovery crawl on the bare credential; run the logged-in portions under per-task session ids; both coexist in one process against one plan.