Simptom ≠ Uzrok: kako je auto-healer postao pravi problem
PostgreSQL primary na 91 % CPU-a. Auto-healer ubija najglasniji query. Sat kasnije: opet 91 %. Lekcija: quickfix-ovi se mogu zaglaviti u beskonačnoj petlji ako nitko ne pita koji se obrazac ponavlja.
PostgreSQL primary na 91 % CPU. Auto-healer ide svakih 5 minuta, pronalazi najglasniji query, šalje pg_cancel_backend(), i load pada na 35 %. Sat kasnije: opet 91 %. Healer ubija sljedeći query. Opet 35 %. Opet sat. Opet 91 %.
Moglo bi se reći da „sustav radi". Ne radi. Troši CPU cikluse boreći se sa simptomom koji nikad ne razumije.
Trenutak iskrenosti
Nakon tri ciklusa smo prestali. Umjesto da agresivnije tuniramo healer, postavili smo pitanje koje smo trebali postaviti od samog početka: Što vraća load?
Odgovor, nakon 20 minuta audita: 14 različitih backend endpointa poziva istu agregaciju preko 1,4 milijuna redaka — COUNT(*) FILTER (...) — bez cache locka. Na svakom cache missu, osam paralelnih uvicorn workera istovremeno ispaljuje isti skupi query. Thundering herd.
Healer je imao pravo da postoje queryji koji ne bi trebali biti aktivni. Healer je imao krivo da ih ubijanje rješava. Problem je bio da je 14 klijenata istovremeno zgrabilo istu kravu za vime.
Što je umjesto toga bilo potrebno
- Po cache ključu točno jedan lock. Koristili smo Redis
SET NX EXkao distributed lock plusasyncio.Lockpo workeru za lokalni short-circuit. - Pronađeno 14 endpointa, tri kritična odmah popravljena, ostalih jedanaest dokumentirano s rokom u tiketu.
- Healer nismo tunirali. Healer uopće nije bio problem.
Nakon fixa: CPU load stabilno na 53 %. Nema više eskalacija. Niti jedan healer ciklus nije potreban.
Meta-lekcija
Svaki sustav ima točku u kojoj simptom djeluje zanimljivije od uzroka. Simptom je glasan, vidljiv i može se „riješiti" kratkim skriptom. Uzrok sjedi tri sloja apstrakcije niže, nema ime i zahtijeva da netko stvarno razumije podsustav.
Pravilo koje sebi postavljamo kod svakog ponovljenog incidenta:
„Ako sada napravimo ovaj fix — što sprečava da za sat vremena opet budemo ovdje?"
Ako odgovor nije jasan, planirani fix nije fix. To je potiskivač simptoma, i sustav će naći drugi, glasniji način da signalizira isti uzrok.
Primjena daleko izvan baza
Isti obrazac poznaje svaki senior inženjer:
- Flaky test? Slijepi retry u CI-ju je potiskivanje simptoma. Test otkriva pravu race condition.
- Memory leak? Pod restart svakih 6 h je potiskivanje simptoma. Leak u međuvremenu žvače korisničke podatke.
- Bounce rate na buttonu? A/B test s novom bojom je potiskivanje simptoma. Feature ne rješava korisnički problem.
Kod svakog ponovljenog problema: identificiraj pet potrošača zahvaćenog podsustava i provjeri obrazac tamo — ne samo na mjestu gdje je alert bio glasan.