Jak připravit aplikaci na škálování bez dluhů

Jak připravit aplikaci na škálování bez dluhů
7min čtení

Jak připravit aplikaci na škálování bez slepých investic: architektura, data, provoz a rozhodnutí, která zabrání drahým opravám při růstu už od začátku.

První větší zákazník často neodhalí problém v obchodním modelu, ale v kódu a provozu. Aplikace začne reagovat pomalu, import dat blokuje běžnou práci, administrace je nepřehledná a každá nová funkce otevírá riziko, že se rozbije něco starého. Otázka, jak připravit aplikaci na škálování, proto nezačíná výběrem cloudové služby. Začíná rozhodnutím, co má systém zvládnout dnes, co pravděpodobně přijde za půl roku a co by bylo předčasné stavět.

Škálování není synonymum pro vysokou návštěvnost. B2B SaaS může mít stovky uživatelů a přesto narazit na limity, protože každý z nich pracuje s tisíci záznamů, generuje dokumenty, importuje tabulky nebo potřebuje rozdílná oprávnění. Mobilní aplikace může mít malý počet aktivních zákazníků, ale vyžadovat spolehlivou synchronizaci v terénu. Příprava proto míří na místa, kde růst zrychluje složitost rychleji, než produkt stíhá vydělávat.

Začněte konkrétním scénářem růstu

Zadání „postavme to škálovatelně“ v praxi nefunguje. Je příliš neurčité a snadno vede buď k podcenění, nebo k drahému systému pro problém, který zatím neexistuje. Před návrhem potřebujeme vědět, jak vypadá pracovní tok uživatele, kde vzniká nejvíc dat a co se nesmí pokazit.

U náborové platformy bývají kritické hromadné importy kandidátů, filtrování rozsáhlé databáze a oddělení dat jednotlivých agentur. U fakturačního systému zase párování dokladů, napojení na externí služby a auditní stopa změn. V obou případech je počet registrací méně podstatný než nejzatíženější operace.

S klienty proto na začátku řešíme několik nepříjemně praktických otázek: Kolik organizací bude systém obsluhovat? Kolik záznamů může jedna organizace vytvořit? Které akce probíhají hromadně? Jak rychle musí uživatel dostat výsledek? A co se stane, když neodpoví externí služba? Odpovědi nejsou smlouvou s budoucností. Jsou podkladem pro rozumný návrh.

Nezačínejte sadou služeb

Pro většinu nových produktů není rozumné začínat sadou samostatných služeb. Rozdělený systém přidává komunikaci mezi službami, nasazování, monitoring, řešení selhání i náklady na změny. Pokud produkt teprve hledá přesný tvar, je často lepší dobře strukturovaný modulární monolit: jedna aplikace, jasně oddělené doménové části a rozhraní, která dovolí pozdější vyčlenění skutečně zatížené oblasti.

Tak se dá dodat funkční produkt s databází, přihlášením, administrací a celým pracovním tokem, aniž by technické řešení předbíhalo realitu. Později může dávat smysl oddělit například generování souborů, vyhledávání nebo zpracování webhooků. Důvodem ale musí být měřitelná zátěž, bezpečnostní hranice nebo nezávislé tempo vývoje, ne obliba určité architektury.

Důležitější než počet služeb je disciplína uvnitř aplikace. Obchodní pravidla nemají být rozházená mezi obrazovkami, databázovými dotazy a náhodnými skripty. Každá oblast, například fakturace, uživatelé, objednávky nebo oprávnění, potřebuje vlastnit svá pravidla a mít srozumitelně definované rozhraní. Díky tomu lze funkci upravit, aniž by změna nečekaně zasáhla polovinu systému.

Databáze je často první skutečný limit

Aplikace se nezpomaluje proto, že má „moc dat“, ale proto, že s nimi pracuje nepromyšleně. Klasika je seznam, který při každém načtení spojuje několik tabulek, filtruje neindexované sloupce a dopočítává hodnoty pro stovky řádků. Horší je, když se totéž opakuje dokola: obrazovka udělá desítky dotazů místo jednoho, kód v cyklu sahá do databáze pro každý řádek zvlášť, nebo se stejný katalog a stejná oprávnění tahají znovu s každým požadavkem. V testovacích datech to projde. U reálného provozu se čekání násobí.

Datový model proto navrhujeme podle běžných dotazů, ne podle hezkého diagramu. Potřebujeme vědět, podle čeho budou lidé vyhledávat, řadit a filtrovat. Index není automatická odpověď na všechno. Příliš mnoho indexů zpomaluje zápis a komplikuje údržbu. U citlivých dotazů ověřujeme chování nad objemem dat, který odpovídá očekávanému provozu.

Ještě před indexem často pomůže, jak se data vůbec čtou: stránkování, jen sloupce které obrazovka potřebuje, předpočítané součty místo agregace při každém otevření seznamu. Redis nebo jiná cache dává smysl u dat, která se čtou často a mění zřídka, relace, oprávnění, číselníky, oblíbené filtry. Není to náhrada za špatný dotaz. Je to způsob, jak do databáze vůbec nechodit, když odpověď už znáte. Cache má cenu jen tam, kde je jasné, kdy data zastarávají.

U více firem v jednom SaaS produktu musí být od začátku jasné také oddělení dat. Každý záznam obvykle patří konkrétní organizaci a toto pravidlo musí platit v databázi, aplikační logice, administraci i exportech. Oprava izolace ve chvíli, kdy už zákazníci data používají, bývá podstatně dražší než správný návrh na začátku.

Oddělte pomalou práci od požadavku uživatele

Uživatel nemá čekat, než systém zpracuje velký import, vytvoří PDF, odešle tisíce notifikací nebo stáhne data z cizího API. Takové úlohy patří do fronty na pozadí. Aplikace potvrdí přijetí požadavku, uloží stav operace a pracovní proces ji provede mimo hlavní webový požadavek.

Úlohy musí být bezpečné při opakovaném spuštění, protože doručení zprávy nebo selhání procesu mohou vést k pokusu navíc. Potřebují také stav, chybový záznam a možnost rozumné opravy. Nestačí jen přidat frontu a doufat, že vše proběhne. Pokud se import zastaví na chybném řádku, administrátor musí vidět proč a uživatel musí vědět, zda má akci opakovat.

Stejný princip platí pro integrace. Externí API občas vrací chybu, mění rychlostní limity nebo je nedostupné. Aplikace na tom nesmí viset bez konce. Nastavujeme časové limity, opakování s odstupem, evidenci neúspěšných volání a jasné chování pro uživatele. Někdy je správné zobrazit aktuální stav, jindy pokračovat bez doplňkové informace. Záleží na tom, zda je externí služba pro daný pracovní tok nezbytná.

Provozní připravenost není práce na poslední týden

Škálovat lze jen to, čemu rozumíme v provozu. Logy, metriky a upozornění nejsou ozdoba infrastruktury. Jsou způsob, jak zjistit, že problém vzniká, dřív než se ozve několik zákazníků. Nestačí sbírat všechna možná data. Potřebujete signály, podle kterých rozhodnete, co se děje a kdo má zasáhnout. Podrobněji o tom, co hlídat po spuštění, píšeme u správy SaaS platformy.

U produkční aplikace sledujeme zejména tyto oblasti:

  • chybovost a dobu odezvy důležitých obrazovek a API operací,
  • vytížení databáze, pomalé dotazy a růst objemu dat,
  • délku front a počet neúspěšných úloh na pozadí,
  • dostupnost a chybovost kritických integrací,
  • bezpečnostní události, neobvyklé přístupy a neúspěšná přihlášení.

K tomu patří zálohy, pravidelně ověřovaná obnova a promyšlené nasazování změn. Záloha, kterou nikdo nikdy nezkusil obnovit, není plán obnovy. Stejně tak nasazení nemá být okamžik, kdy se v produkci ověřuje základní funkčnost. Automatizované testy nepokryjí každý scénář, ale u klíčových toků, přihlášení, platba, vytvoření objednávky, export nebo přidělení oprávnění, výrazně snižují riziko opakovaných chyb.

Bezpečnost a oprávnění rostou s produktem

Na začátku bývá lákavé mít jednu roli administrátora a zbytek uživatelů. Jakmile produkt používají různé typy lidí, přestává to stačit. Obchodník může vidět klienty, ale nemá měnit nastavení fakturace. Vedoucí týmu může spravovat členy vlastní organizace, ale ne uživatele jiného zákazníka. Účetní potřebuje export, nikoli přístup k celé administraci.

Oprávnění je vhodné modelovat podle reálných činností, ne podle názvů pracovních pozic. Kontrola musí být na serveru, ne pouze schovaná v uživatelském rozhraní. U citlivých akcí má smysl auditní záznam: kdo co změnil, kdy a z jakého kontextu. Ne každá aplikace potřebuje stejnou úroveň auditu. Pokud ale systém pracuje s financemi, osobními údaji nebo rozhodnutími s dopadem na zákazníka, bývá audit od začátku levnější než pozdější dohledávání příčin.

Nejdřív měřte, potom optimalizujte

Předčasná optimalizace je drahá hlavně proto, že uzamkne produkt do složitosti, kterou nikdo nepotřebuje. Opačný extrém, ignorovat výkon a provoz až do prvního incidentu, je stejně riskantní. Rozumný postup je postavit čitelný základ, přidat měření a mít připravenou cestu, jak řešit konkrétní úzké hrdlo.

Někdy bude správným krokem přidat index. Jindy stránkovat výsledky, přesunout zpracování do fronty, zvednout cache nebo posílit databázi. Každá z těchto věcí řeší jiný problém. Index zrychlí konkrétní filtr. Fronta uvolní request. Redis ušetří opakované čtení. Silnější databáze pomůže, až kód a model už nemají kam ustoupit. Bez popisu problému a způsobu, jak ověřit výsledek, je každá z nich jen odhad.

V Nextrey stavíme aplikace tak, aby mohly růst bez potřeby přepisovat základ při každém novém zákazníkovi. Neznamená to platit za infrastrukturu pro hypotetické miliony uživatelů. Znamená to rozumět doméně, držet architekturu čitelnou, oddělit náročné operace a provoz skutečně sledovat.

Nejlepší chvíle pro přípravu na škálování je před první zkratkou, která se tváří jako rychlé řešení. Ne proto, aby byl produkt zbytečně složitý, ale aby další dobrá obchodní zpráva nepřinesla technický problém, který zastaví další růst.

Máte nápad, co postavit?

Pracujeme se společnostmi, které potřebují skutečný software postavit a nasadit, a často ho i nadále udržovat. Řekněte nám, co plánujete, a my vám upřímně řekneme, jak bychom k tomu přistoupili.

Ozvěte se nám