M-am lovit de faza asta acum vreo doi ani, la un magazin online destul de măricel. Aveam vreo 12.000 de useri activi lunar și dintr-odată au început să curgă tichetele la suport: „mă scoate din cont imediat ce pun două produse în coș” sau „nu pot să termin comanda că mă trimite la login”. Prima reacție? M-am uitat în DevTools. Cookie-ul era acolo, expires arăta o dată de peste 30 de zile, flag-urile de HttpOnly și Secure erau puse corect. Teoretic, totul părea brici.
Problema e că mulți dintre noi uităm un detaliu fundamental: o sesiune e un contract simetric între browser și server. Dacă browserul tău zice „eu țin minte cheia asta 30 de zile”, dar serverul tău zice „eu am uitat cine ești după 5 minute”, contractul devine nul. Am pierdut vreo 4 ore bune de debug atunci până să realizez că ne uitam în locul greșit.
Primul suspect: In-memory sessions și load balancer-ul
Cea mai clasică greșeală pe care am văzut-o (și pe care am făcut-o și eu în primii ani) e să ții sesiunile în memoria RAM a procesului aplicației. E default-ul în multe librării de Node.js sau Python. Dacă ai un singur server și dai un deploy sau procesul crapă și se restartează (salut, PM2 sau Docker!), ai omorât instantaneu toate sesiunile active.
Dar faza devine și mai frustrantă când ai două sau mai multe instanțe în spate la un load balancer (NGINX, AWS ALB etc.). Dacă nu ai „sticky sessions” (session affinity) activate, userul trimite primul request la Server A și primește un ID de sesiune care există doar în RAM-ul Serverului A. La al doilea request, load balancer-ul îl trimite la Server B. Server B primește cookie-ul, se uită în memoria proprie, nu găsește nimic și-l trimite pe user la login. La proiectul de care ziceam, am rezolvat asta trecând totul pe un Redis extern. Am economisit vreo 30% din timpul de răspuns per total și am scăpat de tichetele de login.
Redis și TTL-ul setat aiurea
Dacă deja folosești Redis sau Memcached pentru sesiuni, nu răsufla ușurat încă. Verifică setările de TTL (Time To Live). Poți să ai max-age la cookie de un an de zile în browser, dar dacă în fișierul de configurare al aplicației (sau în Redis direct) ai o setare de genul session_ttl: 300, datele tale vor fi șterse automat din cache după 5 minute de inactivitate.
Am pățit-o la o migrare de infrastructură unde un coleg a copiat un config de „development” peste cel de „production”. În mediul de dev, pusesem 5 minute special ca să testăm flow-ul de timeout, dar în producție a rămas așa din greșeală. Verifică mereu dacă framework-ul tău nu are un default restrictiv care suprascrie header-ul trimis către browser.
PHP și blestemul Garbage Collector-ului
Pentru cei care încă rulează stack-uri PHP, verificați php.ini. Există o setare numită session.gc_maxlifetime. Chiar dacă tu setezi din cod un timp de expirare lung, Garbage Collector-ul de la PHP s-ar putea să vină „la curățenie” și să șteargă fișierele de sesiune de pe disc dacă timpul acela a trecut. Pe un server cu trafic mare, GC-ul rulează destul de agresiv. Dacă sesiunile tale sunt salvate în folderul default de pe disc, asigură-te că sistemul de operare nu are și el un cron job care curăță folderul ăla mai des decât vrei tu.
Trade-off-ul aici e simplu: sesiuni lungi înseamnă confort pentru user, dar și un risc de securitate mai mare și un consum de resurse crescut pe server. Dacă ții sesiuni de 30 de zile pentru 100k useri în Redis, asigură-te că ai destul RAM.
Voi unde țineți sesiunile de obicei? Direct în baza de date, Redis sau v-ați mutat complet pe JWT-uri ca să scăpați de durerea asta de cap?