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.orgBoth 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:
- Rotating Datacenter and Rotating Unmetered: a session id holds one exit for up to 30 minutes, measured from when it is first assigned. Activity does not extend the window, so work that outlives it should mint a fresh id and continue.
- Residential: best effort, with no fixed duration. The pin lasts as long as the device behind the exit stays online, and the address can change if it goes offline, so your application should handle that change.
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:
- Redirected to a login page mid-crawl, though the credentials never changed.
- A cart that is full on one page and empty on the next.
- CSRF or form-token mismatch errors on submissions that work in a normal browser.
- Pagination restarting, or duplicate early-page rows in your output.
- Intermittency that correlates with concurrency or connection churn, not with any particular URL.
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.