·
8 min čtení
·
Napsal Tomáš Mikeš
Enterprise integrace: 5 věcí, které selhávají v produkci
Každá integrace vypadá v pohodě, dokud producent nemá špatný den. Pět selhávacích scénářů, které v enterprise systémech vidíme opakovaně — a neglamourní opravy, které každý z nich zastaví.
Většina enterprise integrací funguje pro 95 % provozu v pohodě. Těch 5 %, které se rozbije — noční ERP sync, který duplikuje faktury, platební brána, co přestane na jedenáct minut odpovídat, shipping API, které vrátí 200 s error body — sežere většinu provozních nákladů.
Po deseti letech stavění ERP, e-commerce, platebních a datových integrací pro české a evropské klienty se pět selhávacích scénářů vrací znovu a znovu. Každý má neglamourní opravu, kterou 95 % integrací nedělá.
1. Žádná idempotence na straně konzumenta
Klasika: váš systém pošle objednávku do ERP, ERP ji přijme a odpoví, pak zablikne síť a retry na straně klienta spustí duplicitní odeslání. Gratulujeme — právě jste odeslali stejnou objednávku dvakrát.
Opravou je idempotency key. Vygenerujete stabilní, unikátní identifikátor na straně producenta (často UUID navázané na zdrojový event), posíláte ho v každém requestu a od konzumenta vyžadujete, aby si ho pamatoval aspoň den. Když přijde stejný klíč dvakrát, konzument vrátí oběma stejnou odpověď.
Producenti: klíč vždy vygenerujte před prvním pokusem, ne při retry. Konzumenti: persistujte klíč spolu s výsledkem — ne jen „tenhle klíč jsme viděli“, ale „tenhle klíč jsme viděli a výsledek byl X“. Retry musí dostat zpátky stejný výsledek.
2. Synchronní volání přes trust boundaries
Zavoláte externí platební bránu synchronně z checkout endpointu a najednou máte latenci checkoutu navázanou na cizí infrastrukturu. Jejich špatné odpoledne je teď vaše špatné odpoledne. Ještě hůř: pokud je jejich timeout delší než timeout vašeho load balanceru, dostanete napůl dokončené transakce bez deterministické cesty k obnově.
Oprava je standardní „outbox pattern“:
- Váš checkout endpoint zapíše čekající objednávku do vaší vlastní databáze — a ve stejné transakci zapíše řádek do outbox tabulky ve smyslu „odešli tohle na platební bránu“.
- Samostatný worker proces (stejný codebase, jiný deployment) čte z outboxu, volá bránu a výsledek zapisuje zpátky.
- Váš checkout endpoint vrací okamžitě stav „zpracováváme, pošleme e-mail“. UI pollne nebo dostane webhook.
Load balancer nikdy nevidí externí volání. Váš checkout zůstává pod 200 ms. Worker má svůj vlastní timeout a retry logiku, které můžete ladit nezávisle. A když má brána špatné odpoledne, vidíte jen backlog, který se po jejich návratu vyteče během minut.
3. Tichý schema drift
Vaše ERP integrace posílá JSON payload s poli orderId, customerId, total. Za půl roku někdo v ERP týmu přidá taxCode. Váš kód ho nepoužívá, takže si ničeho nevšimnete. Za rok na taxCode závisí byznysové pravidlo — s výjimkou vašeho systému, protože vaše integrace o něm nikdy neslyšela.
Oprava je strojově čitelná smlouva a CI gate. Schéma každého integračního payloadu uložte do repa (JSON Schema, Zod, Pydantic, co k vašemu stacku sedí). Validujte na hranici. Když producent pošle nové pole, o kterém nevíte, buď ho explicitně přijmete (allow-listing), nebo zalogujete varování — nikdy mlčky neignorujte.
A hlavně: když VY změníte schéma, CI by měl PR odmítnout, pokud consumer testy na druhé straně hranice neprojdou. Smlouvy jsou k ničemu, pokud je každá strana aktualizuje nezávisle.
4. Timeouty bez rozpočtů
Distribuované volání má tři timeouty, na kterých záleží: TCP socket timeout, application-level read timeout a SLO deadline volajícího. Většina codebasů nastavuje jenom jeden z nich. Výchozí hodnoty v HTTP klientech jsou typicky katastrofální — Node má výchozí fetch timeout nekonečný, Python requests bude rád viset navždy.
Oprava: nastavte explicitní timeout budget na volání. Pro interní služby berte cokoli nad 500 ms jako patologické. Pro externí služby rozhodujte per-dependency — třeba 3 sekundy na platební bránu, 10 sekund na pomalý ERP batch endpoint. Pak zbývající rozpočet propagujte dolů call chainem: pokud volajícímu zbývají 2 sekundy a tohle volání má být rychlé, nastavte krátký timeout.
A kriticky: když timeout spadne, neznamená to, že se operace neuskutečnila. Znamená to, že nevíte. Vaše recovery logika musí řešit „nevíme, jestli se to stalo“ jako first-class stav — a tím se smyčkou vracíme k idempotenci z bodu 1.
5. Žádná observabilita přes hranice
Váš systém volá ERP, ERP volá legacy SAP modul, SAP modul volá databázi. Něco se rozbije. V roce 2026 pořád běžně vidíme týmy, jak to debugují grepováním tří různých log souborů od tří různých provozních týmů a snaží se rekonstruovat timeline z neshodujících se hodin.
Opravou je distribuované tracing. Jediný korelační ID (W3C trace context je standard — traceparent hlavička) se vygeneruje v nejzazším vstupním bodě a propaguje se každým voláním. Každý log řádek nese ID. Každé odchozí HTTP, gRPC, databázové nebo queue volání ho tagguje.
Nepotřebujete plnohodnotnou APM platformu, abyste začali. Disciplinované correlationId ve strukturovaných logách, prohledávatelné napříč službami, vám dá 80 % hodnoty. Na OpenTelemetry se posuňte, až to objem ospravedlní.
Společná nit
Každá z těchhle oprav existuje proto, že se někdo v produkci tvrdě poučil. Nejsou novinky — outbox pattern je popsaný 15 let, idempotency klíče jsou v každé seriózní API specifikaci, distribuované tracing je dneska samozřejmost. Ale v greenfield enterprise kódu se objevují jen zřídka, dokud si je nevynutí první reálný incident — typicky ve tři ráno.
Architecture-first přístup je prostě tenhle: dejte tohle do designového dokumentu ještě před tím, než se napíše první řádek integračního kódu. Pokud někdo v týmu neumí obhájit, proč je (nebo není) každá z těchhle pěti věcí v designu, nejste ještě s navrhováním hotoví.
Řešíš něco podobného?
Domluvme si 30min technický call. Bez obchodních procesů — přímá architekturní zpětná vazba.