eduardweb.
Ajutor & ÎntrebăriIntermediar#backend#redis#debugging#cookies#sesiuni

Userii pierd sesiunea la 5 minute deși cookie-ul e pe 30 de zile: ce unghi mort ratez?

De Ioan Manole, 5 sept. 2026 · 19 vizualizări · 3 like-uri

Postat 5 sept. 2026

Salutare tuturor. Am o problemă pe un proiect care mă scoate din minți de două zile și am nevoie de o a doua pereche de ochi, fiindcă simt că mă învârt în cerc.

Aplicația e un dashboard B2B pe care avem în jur de 3.200 de useri activi pe zi. De vreo săptămână, suportul a început să fie bombardat cu tichete de la clienți nervoși că sunt scoși afară din cont din senin în timp ce completează formulare lungi. Chestia ciudată e că se întâmplă destul de rapid, la 5 sau 10 minute de la autentificare.

La prima vedere, părea clasicul caz de cookie expirat prost. M-am uitat în DevTools, dar cookie-ul de sesiune pleacă cu Max-Age=2592000 (30 de zile), are SameSite=Lax, Secure, HttpOnly și un Path=/. Pe hârtie, totul e conform manualului.

Ce am eliminat deja din listă

Stack-ul are un backend în Node/Express în spatele unui Nginx pe post de reverse proxy, cu sesiunile salvate într-o instanță separată de Redis. Sesiunile nu stau în memoria procesului, așa că am zis inițial că poate crapă vreun container și se pierde starea. Nu e cazul.

Am verificat următoarele puncte și par complet curate:

  1. Redis memory și evicțiuni: Redis-ul rulează relaxat, stă pe la 18% memorie folosită dintr-un cluster mic de 2GB. Niciun evicted_keys în INFO stats. TTL-ul pe cheia de sesiune din Redis este setat identic cu cookie-ul, adică 30 de zile, cu prelungire automată la fiecare request (rolling: true).
  2. Cluster / Load Balancer: Avem două instanțe de Node.js în spatele lui Nginx. Chiar dacă traficul sare de pe o instanță pe alta (nu avem sticky sessions activate), ambele lovesc aceeași bază de date Redis. Când citesc sesiunea manual prin CLI din Redis cu ID-ul din cookie, cheia e acolo.
  3. Debian/PHP Garbage Collector: Știu că pe PHP clasic există vechiul bug cu cron-ul de sistem care dă wipe la /var/lib/php/sessions la 24 de minute indiferent ce pui în session.gc_maxlifetime. Dar aici suntem 100% pe Node cu connect-redis, deci n-avem treabă cu fișiere temporare de OS.

Unde suspectez că e buba

Am reușit să reproduc comportamentul o singură dată pe contul meu de test. Eram pe o pagină cu un grafic greu care face 4 request-uri paralele prin fetch către API-uri interne. Când am dat refresh, sesiunea s-a evaporat instant și am primit 401 pe linie.

Mă gândesc serios la un race condition pe session save. Când browserul trage 4 request-uri simultan, toate trimit același session ID, dar dacă unul din ele modifică starea sesiunii (sau dacă middleware-ul încearcă să regenereze ID-ul pentru securitate la fiecare hit), cel mai lent request ar putea suprascrie sau invalida ID-ul anterior.

O altă bănuială e legată de Nginx și buffering. Dacă clientul trimite un chunk mare de date și conexiunea se întrerupe, oare e posibil ca header-ul de Set-Cookie să fie trimis gol sau corupt pe vreun retry intern?

Trade-off-ul la mecanismul de rolling sessions e că de fiecare dată când userul atinge o pagină, faci scriere în Redis. Pe volum mic e super ok, pe volume mari poți ajunge la write locks inutile sau suprascrieri accidentale.

A mai lovit cineva o chestie similară? Dacă v-ați bătut de sesiuni invalidate fantomă la câteva minute deși cookie-ul trăiește liniștit în browser, unde ați găsit buba până la urmă?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.