Am o dilemă pe cap și am zis să cer o părere colegială înainte să dau deploy în producție și să iau foc. Un client vechi din e-commerce (aplicația are cam 12k useri activi zilnic și crește) s-a speriat de viitoarele campanii și vrea neapărat să împărțim traficul pe 3 servere diferite. Până acum, totul a rulat impecabil pe o singură cutie cinstită: VPS cu 8 vCPU, Postgres local, Redis local și upload-urile scrise pe disk.
Problema e că n-am mai proiectat de la zero o arhitectură multi-node în producție și nu vreau să complic lucrurile inutil, dar nici să mă trezesc cu race condition-uri sau conexiuni picate la 2 noaptea.
Planul inițial și ce componente vreau să separ
Gândul meu e să scoatem complet starea (state-ul) din serverele de aplicație. Dacă un user trimite o cerere și ajunge pe Serverul A, iar următoarea ajunge pe Serverul B, aplicația trebuie să fie complet agnostică.
După câteva calcule scurte pe foaie, am împărțit stack-ul în câteva bucăți principale:
- Load Balancer în față: Mă gândesc să folosesc un Cloud Load Balancer de la Hetzner sau DigitalOcean pentru SSL termination și Health Checks, ca să nu mă complic la început cu HAProxy configurat manual pe două node-uri de failover.
- Stocarea mediilor: Upload-urile de fișiere trebuie mutate urgent pe S3 sau Cloudflare R2 + CDN. Dacă un client urcă o poză la un produs pe Serverul 1, Serverul 2 n-o va vedea niciodată dacă rămâne pe disk local.
- Sesiuni și Cache: Trecut totul pe un server separat de Redis. Autentificarea devine stateless sau token-urile sunt stocate centralizat în Redis.
Unde încep durerile de cap: Postgres și PgBouncer
Aici e zona unde am cele mai mari semne de întrebare. În prezent, aplicația deschide cam 20-30 de conexiuni la baza de date. Dacă pun 3 servere de aplicație și fiecare își face propriul connection pool (să zicem min 15 - max 50 conexiuni), ajung rapid la 150+ conexiuni directe către Postgres.
Serverul dedicat de DB pe care vreau să mut Postgres-ul va rămâne fără memorie dacă fiecare proces din aplicație deschide conexiuni persistente. Știu că răspunsul standard este PgBouncer pentru connection pooling, dar nu sunt sigur de cea mai curată arhitectură:
- Pun PgBouncer pe același server cu PostgreSQL și mă conectez prin socket sau IP intern?
- Sau pun câte o instanță mică de PgBouncer local pe fiecare dintre cele 3 servere de app?
Iese un trade-off clar aici: dacă pun PgBouncer pe serverul de DB, economisesc resurse pe aplicație, dar creez un singur punct de conexiune. Dacă îl pun pe fiecare app node, am ceva latență suplimentară pe rețea, dar izolez pooling-ul.
Costuri și complexitate deployment
Am făcut un calcul rapid de costuri. Înainte plăteam în jur de 40€/lună pe un singur VPS mare. În noua schemă (1 LB + 3 App Nodes + 1 DB Server + 1 Redis Server + S3/R2), factura sare lejer de 180-220€/lună. Clientul zice că își permite, dar costul banilor e mic pe lângă costul de mentenanță.
Deployment-ul devine și el un mic calvar. Până acum dădeam un git pull și un script de deploy cu reload la PM2. Acum trebuie să orchestrez deploy-ul pe 3 node-uri fără să am downtime (rolling updates pe rând, scoasă instanța din LB, făcut deploy, pusă la loc).
Voi cum ați gestionat prima tranziție de la un monolit pe o singură mașină la o arhitectură distribuită? Ați mers direct pe Kubernetes sau e overkill masiv pentru 3 node-uri? Și legat de PgBouncer, care e abordarea cea mai stabilă în producție?