Serverless na AWS-u za male timove: skaliranje na nulu

Najskuplja stavka u malim sistemima retko je računanje. Najskuplja je mašina koja čeka. Pre nekoliko godina sam gradio integraciju koja je događaje iz jednog sistema pretvarala u akcije u drugom, i skoro sve što je važno u ovom tekstu naučio sam na toj integraciji. Dole je arhitektura, kako je razmišljam, gde se stvarno plaća i gde sam nagazio.
Zašto "skalira na nulu" menja način razmišljanja
Serverless arhitektura koja skalira na nulu znači da kad nema saobraćaja, nema ni računa za računanje. Ne plaćate idle EC2 instancu, ne plaćate kontejner koji drema na tri ujutru. Plaćate izvršavanje, i to je sve.
Za mali tim to je više od cost optimizacije. To je operativna razlika: nema patch-ovanja servera, nema razmišljanja o tome ko će da restartuje proces u subotu, nema kapaciteta koji treba predvideti. Integracija koju sam gradio (AWS + Zendesk, o kojoj više niže) bila je tipičan primer: saobraćaj dolazi u talasima, između talasa je tišina, a ona tišina je većinu vremena.
Trade-off je stvaran i želim da ga imenujem odmah. Dobijate jeftin i low-ops sistem, a plaćate to ograničenjima: vremenski limit izvršavanja, limit veličine payload-a, cold start, i debugging koji je teži nego na lokalnoj mašini. Ako vaš posao ne staje u ta ograničenja, serverless nije odgovor, i bolje je to znati unapred.
Tri komponente i šta svaka stvarno radi
Okosnica je jednostavna: API Gateway prima HTTP zahteve, EventBridge rutira događaje, Lambda izvršava logiku. Dodajte nešto za stanje (kod mene je to najčešće DynamoDB) i imate kompletan sistem.
API Gateway je ulazna vrata. Postoje HTTP API i REST API, i razlika u ceni je značajna: HTTP API košta $1,00 po milionu zahteva za prvih 300M mesečno, dok REST API košta $3,50 po milionu za prvih 333M (cene za US East, N. Virginia). Za većinu malih sistema HTTP API je dovoljan. REST API uzimam samo kad mi trebaju njegove dodatne mogućnosti, a one se retko pokažu kao presudne. Zamka koju vredi znati: HTTP API meri zahteve u koracima od 512 KB, pa se upload od 4,5 MB računa kao 9 zahteva.
EventBridge je mesto gde se događaji razdvajaju od onoga što ih proizvodi. Custom i partner događaji koštaju $1 po milionu primljenih događaja, a događaji se računaju u blokovima od 64 KB, pa se payload od 256 KB naplaćuje kao četiri događaja. Isporuka ciljevima u istom nalogu je besplatna. Praktična posledica: držite događaje malim. Šaljite ID i minimum konteksta, a ne ceo dokument.
Lambda je sam rad. Evo ograničenja koja treba da imate na umu pri dizajnu:
| Parametar | Vrednost |
|---|---|
| Podrazumevani timeout | 3 sekunde |
| Maksimalni timeout (standardna Lambda) | 15 minuta (900 s) |
| Memorija | 128 MB do 10.240 MB |
| Payload, sinhroni poziv | 6 MB zahtev, 6 MB odgovor |
| Payload, asinhroni poziv | 1 MB |
| Skaliranje | do 1.000 novih execution environment-a na 10 sekundi po funkciji |
CPU raste proporcionalno memoriji, a pri 1.769 MB funkcija dobija ekvivalent jednog vCPU-a. Ovo je najčešće pogrešno podešena stvar koju viđam: ljudi ostave 128 MB jer "ionako samo šalje jedan HTTP poziv", pa se čude zašto im funkcija radi sporo. Sporije izvršavanje se naplaćuje duže, tako da veća memorija ponekad ispadne jeftinija. Merite, ne pogađajte.
Kako izgleda tok događaja u praksi
Evo kostura sistema kakav bih postavio za tipičnu integraciju dva SaaS alata, gde jedan šalje webhook, a drugi treba da dobije obogaćenu akciju:
Webhook (spoljni sistem)
-> API Gateway (HTTP API)
-> Lambda "ingest" (validira, odmah vraća 200, šalje događaj)
-> EventBridge (custom bus, pravila po tipu događaja)
-> Lambda "process" (poslovna logika, poziva spoljni API)
-> Lambda "notify" (obaveštenja)
-> DynamoDB (idempotency ključevi, stanje)
Ključna odluka je razdvajanje prijema od obrade. Ingest funkcija radi minimum: proveri potpis, upiše događaj na bus i vrati odgovor. Sva teška logika ide iza EventBridge-a. Razlog je praktičan: spoljni sistemi koji šalju webhook-ove imaju sopstvene timeout-e i retry politike, i ne želite da vaša spora obrada izazove duplikate samo zato što pošiljalac nije dočekao odgovor.
Drugo pravilo, bez kojeg ne puštam ništa u produkciju: idempotentnost. EventBridge i Lambda mogu da isporuče isti događaj više puta. Svaki događaj nosi jedinstveni ključ, a prvi korak u process funkciji je uslovni upis tog ključa u DynamoDB. Ako ključ već postoji, funkcija tiho izlazi.
// idempotency guard, pojednostavljeno
try {
await ddb.put({
TableName: "idempotency",
Item: { pk: event.id, ttl: nowPlusDays(2) },
ConditionExpression: "attribute_not_exists(pk)",
});
} catch (e) {
if (e.name === "ConditionalCheckFailedException") return; // već obrađeno
throw e;
}
Bez ovoga dobijate duple tikete, duple mejlove ili duple naplate, i to uvek u najgorem trenutku.
Za zakazane poslove koristim EventBridge Scheduler, koji uključuje 14 miliona besplatnih poziva mesečno, pa se zakazani zadaci praktično ne osete na računu.
Šta ovo košta: ilustrativna računica
Cene ispod su ilustracija, ne ponuda. Uzete su iz javnih cenovnika za US East i treba ih proveriti na zvaničnim AWS stranicama pre nego što se oslonite na njih, naročito ako radite u EU regiji, gde se cene razlikuju. Jedan od izvora nije zvanični AWS cenovnik, pa je provera obavezna.
Pretpostavimo okrugao primer: 1 milion događaja mesečno, svaki prolazi kroz API Gateway, EventBridge i jednu Lambda funkciju.
| Stavka | Računica | Iznos |
|---|---|---|
| API Gateway (HTTP API) | 1M x $1,00 / M | ~$1,00 |
| EventBridge (custom događaji) | 1M x $1,00 / M | ~$1,00 |
| Lambda zahtevi | prvih 1M u besplatnom nivou, posle $0,20 / M | ~$0 |
| Lambda trajanje | zavisi od GB-sekundi, besplatnih 400.000 GB-s mesečno | ~$0 pri kratkim funkcijama |
| DynamoDB on-demand | 1M upisa x $0,625 / M | ~$0,63 |
Ukupno: nekoliko dolara mesečno za milion događaja. Trajanje na x86 košta $0,0000166667 po GB-sekundi, a ARM (Graviton2) je 20% jeftiniji, pa ako vam biblioteke to dozvoljavaju, prelazak na ARM je skoro besplatna ušteda.
Dva upozorenja o ceni:
- DynamoDB cene se u izvorima razilaze. Neki navode $1,25 po milionu write unita, noviji $0,625. Verovatno je starija cifra zastarela, ali ne tvrdim to, proverite na AWS stranici. Za male sisteme razlika je zanemarljiva, ali u računici je ne smete uzeti zdravo za gotovo.
- Besplatni nivo za nove naloge se promenio. Besplatni nivo API Gateway-a (1M poziva mesečno 12 meseci) važi samo za naloge otvorene pre 15. jula 2025. Noviji nalozi dobijaju kredite umesto toga, a tačan iznos nisam mogao da potvrdim iz zvaničnog izvora. Ne gradite poslovni slučaj na besplatnom nivou.
Još jedna stvar koja je promenila računicu: od 1. avgusta 2025. AWS naplaćuje INIT fazu (cold start) za sve konfiguracije Lambde. Ranije je ta faza bila besplatna za ZIP funkcije na managed runtime-ovima. Koliko to utiče na vaš račun zavisi od runtime-a i obrasca saobraćaja, pa ne navodim procente. Praktičan savet je isti kao i ranije: držite deployment paket malim, a inicijalizaciju (klijenti, konekcije) izvan handler-a, da se izvrši jednom po environment-u.
Gde serverless puca i kako sam to naučio
Najvažnije što bih rekao kolegi koji prvi put gradi ovakav sistem: limiti su dizajnerska ograničenja, ne tehničke sitnice.
- Timeout. Lambda može do 15 minuta, ali to ne znači da treba da ga koristite. Ako posao traje duže ili je nepredvidiv, razbijte ga na korake ili ga pomerite na drugu vrstu računanja. Za asinhrone pozive postoji i varijanta Lambda Managed Instances sa timeout-om do 90 minuta, ali to je specifična konfiguracija sa drugačijim modelom, ne zamena za dobar dizajn.
- Payload. Sinhroni poziv trpi 6 MB, asinhroni samo 1 MB. Ako vam događaji rastu, stavite sadržaj u S3 i šaljite referencu. Takođe izbegava množenje troška u 64 KB blokovima EventBridge-a.
- Spoljni API-ji su vaš pravi usko grlo. Lambda se skalira do 1.000 novih okruženja na 10 sekundi, što je daleko više nego što će spoljni servis (tipično sa strogim rate limit-om) podneti. Ako ne ograničite konkurentnost (reserved concurrency) na funkciji koja zove spoljni API, sopstvenim uspehom ćete ga srušiti, a on će vas blokirati. Ovo sam naučio na teži način.
- Integracioni timeout API Gateway-a je strožiji od Lambdinih 15 minuta. Tačnu vrednost ne navodim jer je nisam potvrdio u zvaničnoj dokumentaciji, ali dizajnirajte tako da HTTP odgovor vraćate brzo, a pravi posao radite asinhrono. To je ionako razlog za razdvajanje ingest-a i obrade.
Posebna priča je observability. Na serveru koji stoji, uđete i pogledate log. Ovde su logovi raspršeni po funkcijama. Uvek ubacujem correlation ID koji prati događaj kroz sve korake, i alarm na dead-letter red za događaje koji su iscrpli pokušaje. Sistem bez DLQ-a gubi događaje tiho, a tihi gubitak je najgora vrsta greške.
Šta bih ja uradio
Ako bih danas krenuo od nule sa malim timom, uradio bih ovo:
- HTTP API, ne REST API, osim ako nešto konkretno ne traži suprotno. Tri i po puta jeftinije i dovoljno za većinu slučajeva.
- Ingest i obradu razdvojiti od prvog dana. Brz odgovor, događaj na bus, sve teško iza.
- Idempotentnost kao pravilo, ne kao optimizacija. Svaki handler mora biti bezbedan za dupli poziv.
- ARM tamo gde biblioteke dozvoljavaju, i memoriju podesiti merenjem.
- DLQ i alarm pre prvog korisnika, ne posle prvog incidenta.
- Reserved concurrency na svemu što zove spoljni API.
- Cene proveriti ručno za svoju regiju pre nego što ih ubacite u bilo koju prezentaciju ili ponudu.
I jedna iskrena napomena: serverless nije uvek pravi izbor. Ako imate stalan, predvidiv, visok saobraćaj ili dugotrajne procese, kontejner koji stalno radi može biti jeftiniji i jednostavniji. "Skalira na nulu" je velika prednost samo ako ste zaista često na nuli.
Zatvaranje
Ovakva arhitektura je ono što je meni omogućilo prvu usklađenost sa SLA u integraciji AWS + Zendesk, bez ijednog servera za održavanje. Ako razmišljate o sličnom sistemu za svoj tim i želite da proverite da li serverless ima smisla za vaš slučaj, javite se na lazar-milicevic.com/#contact, rado ću pogledati šta imate.
Izvori za limite i cene: Lambda quotas, Lambda timeout konfiguracija, AWS Lambda Pricing Calculator & Cost Guide, AWS API Gateway Pricing Calculator & Guide, AWS EventBridge Pricing guide, DynamoDB Pricing. Cene su iz sekundarnih izvora i važe za US regije, proverite ih na zvaničnim AWS stranicama.
Često postavljana pitanja
Šta znači da serverless na AWS-u skalira na nulu?
Kada nema saobraćaja, nema ni računa za računanje: ne plaćam idle EC2 instancu niti kontejner koji miruje usred noći. Plaćam samo stvarno izvršavanje. Za mali tim to znači i manje operative, jer nema patch-ovanja servera ni planiranja kapaciteta.
Koje su glavne mane serverless pristupa na AWS-u?
Jeftin i low-ops sistem plaća se ograničenjima: vremenskim limitom izvršavanja, limitom veličine payload-a, cold start-om i težim debugging-om nego lokalno. Standardna Lambda ima maksimalni timeout od 15 minuta, a sinhroni poziv do 6 MB payload-a. Ako posao ne staje u ta ograničenja, serverless nije pravi izbor.
Koja je razlika u ceni između HTTP API i REST API u API Gateway-u?
Po ilustrativnim cenama za US East, HTTP API košta $1,00 po milionu zahteva za prvih 300M mesečno, a REST API $3,50 po milionu za prvih 333M. Za većinu malih sistema HTTP API je dovoljan, pa REST API uzimam samo kad mi trebaju njegove dodatne mogućnosti. HTTP API zahteve meri u koracima od 512 KB, pa se upload od 4,5 MB računa kao 9 zahteva.
Zašto je idempotentnost važna u serverless sistemu sa EventBridge-om i Lambdom?
EventBridge i Lambda mogu da isporuče isti događaj više puta, što bez zaštite daje duple tikete, mejlove ili naplate. Zato svaki događaj nosi jedinstveni ključ, a prvi korak obrade je uslovni upis tog ključa u DynamoDB. Ako ključ već postoji, funkcija tiho izlazi bez ponovne obrade.
Kako da podesim memoriju Lambda funkcije da bude brza, a ne skupa?
CPU kod Lambde raste proporcionalno memoriji, a pri 1.769 MB funkcija dobija ekvivalent jednog vCPU-a. Česta greška je ostavljanje 128 MB, zbog čega funkcija radi sporo, a sporije izvršavanje se naplaćuje duže. Zato veća memorija ponekad ispadne jeftinija, pa treba meriti umesto pogađati.
Gradiš nešto teško sa AI-jem ili automatizacijom? Otvoren sam za razgovor.
Javi se