Salutare tuturor. Am avut recent un caz destul de frustrant la un magazin online cu vreo 12k useri activi zilnic, unde ne-am bătut capul trei zile cu o problemă aparent stupidă.
Userii se plângeau că sunt deconectați după doar câteva minute de inactivitate. În browser, cookie-ul de sesiune era setat corect cu un Max-Age de 30 de zile. Pe hârtie, totul trebuia să meargă strună. În realitate, după o scurtă pauză de cafea, bam! Redirect la login.
Dacă ați trecut prin asta, știți cât de enervant este. Clientul urlă că-și pierde clienții din checkout, iar în loguri nu se vede nimic suspect la prima vedere. După câteva ore de debug intens, am mapat cele mai comune trei locuri unde se rupe filmul în astfel de scenarii.
1. Serverul uită cine ești, chiar dacă browserul își amintește
Asta e cea mai clasică greșeală de configurare. Browserul trimite cuminte cookie-ul cu ID-ul de sesiune la fiecare request. Dar dacă serverul nu mai are acel ID în baza de date sau în Redis, te dă afară instant.
Implicit, multe framework-uri folosesc un "in-memory session store" sau fișiere locale temporare. Dacă procesul de Node.js sau PHP-FPM își dă restart (de exemplu, la un deploy automat sau când atinge limita de RAM), toată memoria se șterge. Pentru user, asta înseamnă logout instantaneu, deși cookie-ul lui e valid în browser încă 30 de zile.
Soluția: Nu folosiți niciodată session store-ul default în producție. Puneți un Redis sau măcar o tabelă în baza de date pentru asta.
2. Configurațiile de Garbage Collection (GC) și TTL-ul din Redis
La proiectul de care vă ziceam, foloseam Redis pentru sesiuni. Toate bune, doar că cineva configurase greșit politica de maxmemory-policy în Redis. Când memoria se umplea (aveam o instanță mică, de doar 1GB), Redis începea să șteargă chei la întâmplare ca să facă loc, folosind algoritmul allkeys-lru.
Sesiunile active de 5 minute zburau primele pentru că erau considerate inactive în acel micro-secund de spike de trafic. La fel se întâmplă și în PHP cu session.gc_maxlifetime. Chiar dacă pui cookie-ul pe 30 de zile din frontend, dacă pe server GC-ul rulează la 24 de minute, serverul va șterge fișierele de sesiune de pe disc mult mai devreme decât expiră cookie-ul.
3. Coșmarul din spatele Load Balancer-ului (Sticky Sessions)
Dacă ai mai mult de un server web în spatele unui Load Balancer (AWS ALB, Nginx) și folosești sesiuni locale pe disc sau în memoria serverului, ai încurcat-o. Fără "sticky sessions" (sau session affinity) activate pe Load Balancer, primul request se duce pe Serverul A (care îți creează sesiunea), iar al doilea request se duce pe Serverul B.
Serverul B habar n-are cine ești, așa că îți cere să te loghezi din nou. Pare că te deconectează la 5 minute, dar de fapt te deconectează imediat ce Load Balancer-ul decide să trimită traficul pe alt nod.
Trade-off-ul pe care trebuie să-l accepți
Poți rezolva asta rapid cu sticky sessions, dar asta înseamnă că dacă Serverul A pică, toți userii de pe el își pierd sesiunea. Alternativa corectă este un session store centralizat (Redis). Da, adaugă o mică latență de 2-5ms la fiecare request pentru că trebuie să interoghezi baza de date de sesiuni, dar scapi de bug-uri de genul ăsta și poți scala orizontal fără stres.
Voi cum gestionați sesiunile persistente la proiectele mari? Mergeți pe Redis clasic sau ați trecut complet pe JWT-uri stocate în cookie-uri securizate?