← Portfolio Case Study

Silnik wypłat — gdy system no-code zawodzi po cichu przy skali

Klient: Branża usługowa Czas: ~1 tydzień
Base44 Deno TypeScript React Telegram API GitHub CI

Przed

  • Wypłata 18 080 CHF domknięta w połowie — a system zgłosił sukces
  • Setki zapisów z przeglądarki uderzały w rate limit platformy
  • Ciche try/catch połykało każdy błąd — brak alertu, brak rollbacku
  • Wypłata 210 rekordów: ~126 s i tak padała powyżej 100 rekordów

Po

  • Operacje masowe: ~272 wywołania HTTP zwinięte do ~10
  • 210 rekordów w 3,9 s — ~32x szybciej
  • Maszyna stanów wypłaty + nocny audyt + alerty Telegram
  • Naprawa jednym kliknięciem; wdrożenie z zerowym przestojem

Punkt wyjścia

Powracający klient (branża usługowa) prowadzi dwa bliźniacze studia na platformie no-code (encje + funkcje brzegowe Deno, 2-way sync z GitHub). Recepcja rejestruje usługi, prowadzi kasę zmianową i wypłaca pracownice. Po wcześniejszym ratunku system był stabilny — do czasu, aż urósł wolumen.

Problem

Wiadomość, od której się zaczęło: pojedyncza wypłata na 18 080 CHF, obejmująca 212 rekordów, przeszła tylko dla około połowy z nich — a system zgłosił sukces i poszedł dalej.

  • Cicha awaria w połowie: oznaczonych zostało ~100 z 212 rekordów. Funkcja i tak doszła do końca i zapisała log audytu, więc wypłata wyglądała na domkniętą, a stan był niespójny.
  • Zapisy z przeglądarki: cała wypłata wysyłała setki pojedynczych aktualizacji rekordów prosto z klienta. Powyżej ~200 operacji uderzała w rate limit platformy.
  • Połknięte błędy: try/catch po cichu pochłaniał każdy nieudany zapis — bez alertu, bez rollbacku, bez statusu. Nic nie sygnalizowało, że zadziałało tylko częściowo.
  • Szkody uboczne: ręczny ratunek nadpisał 11 rekordów ustawień dziennych błędnym odniesieniem do wypłaty — utajone ryzyko podwójnego naliczenia.

Diagnoza

Oczywista hipoteza brzmiała „za duża współbieżność". Obaliłem ją serią kontrolowanych testów obciążeniowych:

  • Współbieżność 10, bez retry: 100 / 217 oznaczonych, 117 błędów rate-limit.
  • Współbieżność 5 + retry: 25 / 215 — gorzej; retry tylko zwielokrotnia liczbę operacji.
  • Współbieżność 3, czyste 210: 200 / 210.

Wzorzec był jasny: wąskim gardłem była łączna liczba operacji zapisu (~250+) w jednej funkcji — nie współbieżność ani opóźnienia między nimi. Strojenie nigdy by tego nie naprawiło; trzeba było zmienić architekturę.

Rozwiązanie

1. Operacje masowe zamiast zapisów per rekord

SDK platformy ma endpointy masowe — do 500 rekordów na jedno wywołanie HTTP. Przepisałem wypłatę tak, by każdy krok wielorekordowy szedł paczkami (helper tnie na strony po 500). ~272 wywołania zwinęły się do ~10, a wypłata 210 rekordów spadła z ~126 s (padającej) do 3,9 sekundy.

2. Prawdziwa maszyna stanów na każdej wypłacie

Każda wypłata startuje jako pending i staje się committed dopiero, gdy wszystkie kroki się powiodą — w przeciwnym razie failed, z zapisaną listą kroków, które padły. Żadna operacja nie może skończyć „w połowie" i udawać, że jest dobrze. Pełna idempotencja sprawia, że retry nigdy nie naliczy podwójnie.

3. Monitoring, który się odzywa — i tylko wtedy

Zaplanowany nocny audyt skanuje ostatnie wypłaty pod kątem niespójności i pinguje właściciela na Telegramie tylko wtedy, gdy coś jest nie tak. Gdy wszystko jest czyste — milczy. Powiadomienie pracownicy wychodzi dopiero po udanym commicie.

4. Naprawa jednym kliknięciem

Każda wypłata zawieszona w pending lub failed pojawia się w interfejsie jako czerwony baner z przyciskiem „Dokończ wypłatę" — idempotentna procedura naprawcza, która bezpiecznie domyka brakujące zapisy. Rzadka awaria staje się jednym kliknięciem, a nie operacją na danych.

Rezultat

Oba studia działają teraz na tym samym silniku. Wypłata 210 rekordów zajmuje ~3,9 sekundy i nie może już paść po cichu: jeśli cokolwiek się zepsuje, właściciel wie o tym zanim dowie się pracownica, i naprawia to jednym kliknięciem. Audyt ostatnich 30 dni potwierdził, że poza pierwotnym incydentem wszystkie historyczne wypłaty są czyste. Całe wdrożenie odbyło się z zerowym przestojem produkcji — stary mechanizm został jako 30-sekundowy rollback, a każda zmiana była testowana na koncie jednorazowym, nigdy na danych prawdziwych pracownic.

Wnioski

Naprawa, która naprawdę się liczyła, nie dotyczyła szybkości — tylko widoczności. System obracający pieniędzmi nigdy nie może mieć prawa paść po cichu. Gdy wypłaty ruszają realną gotówką, „doszło do końca bez wyjątku" to nie to samo co „zadziałało".

Platformy no-code skalują się znakomicie — do momentu, gdy pojedyncza operacja musi dotknąć setek rekordów naraz. To jest granica, na której kończy się „klikanie razem", a zaczyna inżynieria: batchowanie, atomowość, idempotencja, monitoring.

Masz podobny problem?

Opisz go AI — zbierze kontekst techniczny, Artur przygotuje wycenę w 48h.

Rozpocznij diagnostykę