Serverless chat na AWS-u: 19 $ mjesečno za 100 korisnika i njegove granice
U grupama od deset jedan server postaje jeftiniji na oko 1.200 korisnika. Nove konekcije ostaju ograničene na 500 u sekundi po AWS računu dok AWS ne poveća kvotu.
Vodiči za izradu chat aplikacije na AWS-u rijetko kažu dokle takva aplikacija može ići. Ovdje su arhitektura, troškovi za sedam veličina i četiri ograničenja zbog kojih na kraju morate preći na drugo rješenje. Nijedno od njih ne možete podići tako što ćete više platiti: tri su fiksna, a četvrto, 500 novih konekcija u sekundi, mijenja se samo ako vam AWS poveća kvotu.
Arhitektura
Sastoji se od pet dijelova.
API Gateway WebSocket API drži otvorene sockete. To je jedina komponenta koja zna da konekcija postoji.
Lambda obrađuje najmanje četiri rute: $connect, $disconnect, $default i rutu za slanje. Funkcija radi onoliko milisekundi koliko joj treba za obradu jedne poruke i onda se gasi.
Redis čuva mapu konekcija, a u chat aplikaciji i više od toga: prisutnost korisnika, pub/sub za fan-out između instanci funkcije i indikatore kucanja, ako ih želite. Redis je ovdje bolji izbor od baze dokumenata, jer aplikacija ID-eve konekcija i čuva i koristi za broadcast.
DynamoDB ili Postgres čuva same poruke. Isporuka i trajnost su odvojeni problemi, pa historiju chata ne držite u skladištu konekcija.
Management API je način na koji Lambda šalje poruku nazad kroz socket koji nije sama otvorila. Taj detalj je uzrok iznenađenja na računu, opisanog u nastavku.
7,30 $ mjesečno prije ikakvog saobraćaja
Lambda koja čita iz ElastiCachea mora biti u VPC-u. API Gateway Management API je javni endpoint, a Lambda iz VPC-a do njega ne može doći bez izlazne rute.
Zato vam treba ili NAT Gateway za 32,85 $ mjesečno ili interface endpoint za 7,30 $ po zoni dostupnosti. Nijedno ne raste sa saobraćajem i oba se plaćaju, slao iko poruku ili ne.
Ovo nisam vidio ni u jednom kalkulatoru cijena, a na maloj skali to je velik dio računa.
Koliko košta
API Gateway na računu ima dvije stavke:
| Cijena | |
|---|---|
| Poruke, u oba smjera | 1,00 $ po milionu, obračun u koracima od 32 KB |
| Minute konekcije | 0,25 $ po milionu |
Jedna stalno otvorena konekcija košta 1,08 centi mjesečno, a milion poruka jedan dolar. Sve tabele ispod izračunate su iz te dvije brojke.
Ovo je mjesečni minimum prije ikakvog saobraćaja:
| Serverless | Stalni server | |
|---|---|---|
Redis (cache.t4g.micro, Valkey) | 9,34 $ | 9,34 $ |
| VPC interface endpoint | 7,30 $ | — |
Instanca (m7g.medium, nije burstable) | — | 29,78 $ |
| Minimum | 16,64 $ | 39,12 $ |
Kolona sa serverom računa s instancom koja nije burstable. t4g.small izgleda jeftinije, sa 12,26 $, ali trajno daje 0,4 vCPU. Fan-out znači jedan JSON.stringify i jedan upis u socket po primaocu, a svako ponovno povezivanje troši 1–5 ms procesora na TLS handshake. Kad se nekoliko hiljada korisnika ponovo povezuje svakih deset minuta, handshakeova u sekundi ima dovoljno da potroše kredite. Poređenje serverlessa s burstable instancom zato ide u korist serveru.
Veličina grupe množi račun
Po fan-outu se aplikacija za poruke razlikuje od drugih WebSocket opterećenja. API Gateway svaku poruku naplati jednom kad stigne i još po jednom za svakog primaoca, pa kad u grupi od pedeset članova neko jednom otkuca poruku, API Gateway je naplati pedeset puta.
Evo istih sto korisnika, od kojih svaki šalje pedeset poruka dnevno, a mijenja se samo veličina grupe:
| Veličina grupe | Naplaćenih poruka/mjesec | Serverless |
|---|---|---|
| Samo 1:1 | 300.000 | 17,41 $ |
| Grupe po 10 | 1.500.000 | 18,72 $ |
| Grupe po 50 | 7.500.000 | 25,27 $ |
Broj poslanih poruka isti je u sva tri reda. Promijenio se samo broj primalaca, a s njim i račun.
Račun za sedam veličina
Ove brojke računaju s grupama po deset, što je otprilike prosjek stvarne chat aplikacije:
| Korisnika | Poruka/mjesec | Serverless | Jedan server | HA par |
|---|---|---|---|---|
| 100 | 1,5M | 18,72 $ | 39,27 $ | 85,48 $ |
| 500 | 7,5M | 27,02 $ | 39,82 $ | 86,03 $ |
| 1.000 | 15M | 37,49 $ | 40,51 $ | 86,72 $ |
| 2.500 | 37,5M | 69,07 $ | 42,58 $ | 88,79 $ |
| 5.000 | 75M | 121,70 $ | 46,04 $ | 92,25 $ |
| 10.000 | 150M | 226,95 $ | 52,95 $ | 99,16 $ |
| 25.000 | 375M | 542,70 $ | 96,83 $ | 166,18 $ |
Na sto korisnika sve košta manje od devetnaest dolara mjesečno, a od toga je šesnaest dolara minimum. Sam saobraćaj košta dva dolara.
Gdje serveri postaju jeftiniji
| Veličina grupe | Naspram jednog servera | Naspram HA para | Poruka/mjesec na pragu za HA par |
|---|---|---|---|
| 1:1 | 3.000 korisnika | 9.000 | 27M |
| Grupe po 5 | 1.900 | 5.700 | 43M |
| Grupe po 10 | 1.200 | 3.550 | 53M |
| Grupe po 20 | 700 | 2.000 | 60M |
| Grupe po 50 | 300 | 900 | 68M |
Prag isplativosti mjeren u korisnicima pada kako grupe rastu: devet hiljada za razgovore jedan-na-jedan, devetsto za grupe po pedeset. Prag mjeren u porukama raste, sa 27 miliona na 68 miliona.
Fan-out, dakle, spušta broj korisnika na kojem serveri postaju jeftiniji, a podiže broj poruka na kojem se to dešava. Razlog je na strani servera: server koji svaku poruku šalje na pedeset primalaca troši procesor za svakog od njih, pa mu veća instanca treba ranije. Fan-out poskupljuje obje arhitekture, samo što kod serverlessa trošak raste ravnomjernije.
U praksi, ako je aplikacija jedan-na-jedan, serverless je bez problema dovoljan i za više od nekoliko hiljada korisnika. Ako ima velike grupe, prelazak planirajte na otprilike hiljadu korisnika.
Četiri ograničenja koja određuju kada mijenjate arhitekturu
Za razliku od cijene, na ova ograničenja uglavnom ne možete uticati: tri od četiri se uopšte ne mogu podići, a prvo samo ako AWS odobri veću kvotu.
500 novih konekcija u sekundi, po AWS računu, po regionu
Ovo ograničenje određuje plafon, a rijetko ko ga spominje.
Svaka konekcija se zatvara nakon dva sata, bez obzira na aktivnost, a zatvara se i svaki socket koji deset minuta miruje. Zato se klijenti stalno ponovo povezuju, a u stabilnom stanju broj ponovnih povezivanja u sekundi jednak je broju istovremenih korisnika podijeljenom s trajanjem sesije.
| Klijent se ponovo povezuje svakih | Najviše istovremenih korisnika |
|---|---|
| 10 minuta | 300.000 |
| 30 minuta | 900.000 |
| 120 minuta (gornja granica) | 3.600.000 |
Bez veće kvote od AWS-a tabela iznad je gornja granica. Iz toga slijedi i nešto za dizajn: što duže socket ostaje otvoren, to više korisnika isti AWS račun može podnijeti. Klijent koji šalje ping kako bi ostao ispod desetominutne granice neaktivnosti, umjesto da se ponovo povezuje, dobija tri puta više prostora uz sesije od 30 minuta, a dvanaest puta više uz najduže dozvoljene sesije od dva sata.
Ograničenje važi za cijeli AWS račun, pa drugi WebSocket API u istom regionu dijeli istu kvotu.
Najduže trajanje konekcije: 2 sata
Pošto se svaki socket zatvara nakon dva sata, korisnik koji cijeli dan drži otvorenu aplikaciju ponovo se poveže najmanje dvanaest puta, a svako povezivanje upiše novi unos u skladište konekcija.
Na dugotrajnu konekciju ne možete računati, pa ponovno povezivanje ugradite od prvog commita, umjesto da ga kasnije dodajete kao funkciju za otpornost.
Istek neaktivnosti od 10 minuta
Socket bez saobraćaja zatvara se nakon deset minuta. U chat aplikaciji to važi za većinu socketa većinu vremena, jer ljudi mnogo više čitaju nego što kucaju.
Treba vam keepalive koji je dovoljno ispod granice od deset minuta; uobičajeno je pet do sedam minuta. Keepalive je poruka, pa se naplaćuje. Na razmaku od sedam minuta to je oko 6.200 pingova po korisniku mjesečno, otprilike 0,6 centi po korisniku. Na hiljadu korisnika to je 6 $ mjesečno samo za pingove koji drže konekcije otvorene, više od polovine onoga što za iste korisnike koštaju minute konekcije.
128 KB po poruci, naplata u koracima od 32 KB
Poruka od 33 KB naplaćuje se kao dvije. Prilozima nije mjesto na socketu: stavite ih u object storage i pošaljite ključ.
Dva blaža ograničenja
Lambda concurrency je po defaultu 1.000 po regionu. Uz 50 ms po pozivu to je 20.000 poruka u sekundi prije throttlinga, što nećete dostići slučajno, a ograničenje se može i povećati.
Timeout integracije je 29 sekundi, što je problem samo ako handler radi nešto što ne bi trebao.
Šta bih gradio za svaku veličinu
Ispod hiljadu korisnika ovu arhitekturu bih izabrao bez razmišljanja. Na sto korisnika košta devetnaest dolara mjesečno, bez servera koji treba krpiti. Saobraćaj je 10% tog računa, pa optimizacijom nemate šta dobiti.
Od hiljadu do pet hiljada korisnika ova arhitektura je i dalje u redu za razgovore jedan-na-jedan, a za velike grupe postaje skupa. Tada vrijedi provjeriti šaljete li poruke koje vam ne trebaju. Ako deset ažuriranja prisutnosti spojite u jedno, njihov trošak pada deset puta, a infrastrukturu ne dirate. To je jedina optimizacija u ovom modelu koju vrijedi uraditi prije promjene arhitekture.
Iznad pet hiljada korisnika, ili iznad pedeset miliona poruka mjesečno, sloj socketa bih preselio na servere iza load balancera, a sve ostalo zadržao. Redis, skladište poruka i klijentski protokol ostaju. Mijenjate jednu komponentu umjesto da prepisujete aplikaciju, i zato sloj konekcija od početka treba biti tanak.
Iznad 300.000 istovremenih korisnika dolazite do ograničenja koje AWS račun po defaultu ima za nove konekcije. Pomjera ga samo veća kvota od AWS-a, a sistem te veličine traži drugu arhitekturu i poseban tekst.
Šta serverless štedi: oko 23 $ mjesečno
Serverless WebSocketi su jeftini zato što ne plaćate instancu koja stoji neiskorištena. Ta ušteda iznosi oko 23 $ mjesečno, koliko je razlika između dva minimuma.
Sve iznad minimuma naplaćuje se po potrošnji. Na dvadeset pet hiljada korisnika u grupama po deset plaćate više od tri puta koliko košta par servera.
Tačka u kojoj se linije troškova sijeku manje je bitna od pitanja vrijedi li razlika u cijeni više od pažnje koju server traži. Na sto korisnika dvadeset dolara mjesečno za to da nikad ne razmišljate o serveru očigledno se isplati. Na dvadeset pet hiljada korisnika serverless košta oko tristo osamdeset dolara mjesečno više od dva servera. O tome neko treba odlučiti svjesno, umjesto da tu odluku naslijedi od prototipa koji je radio.
Sve brojke su cijene iz cjenovnika za US East od sredine 2026. godine, bez besplatnog nivoa na API Gatewayu i s primijenjenim trajnim besplatnim nivoom Lambde. Izvan računice su LCU naknade za load balancer, prenos između zona dostupnosti, rezervne kopije, rezervisane cijene i skladištenje poruka, a nekoliko tih stavki podiglo bi kolonu sa serverom. Ovo je računica na osnovu objavljenih cijena, a ne mjerenje sistema u radu.
Blog
Ako radite na nečemu sličnom, javite nam se s detaljima.
Prvi poziv traje 30 minuta i ni na šta vas ne obavezuje.