Sklep zwalnia? Pierwsza reakcja większości agencji i właścicieli e-commerce jest przewidywalna: „Dzwonimy do hostingu, kupujemy mocniejszy VPS albo serwer dedykowany”. Faktura rośnie dwukrotnie, księgowy łapie się za głowę, a sklep... dalej muli.
Dlaczego? Ponieważ żaden procesor ani dodatkowy RAM nie naprawią błędów architektonicznych i konfiguracyjnych w kodzie. Hardware ma swoje limity, a zoptymalizowany kod skaluje się znacznie taniej.
Jeśli śledzicie moją aktywność w mediach społecznościowych, to doskonale wiecie, że od lat walczę z mitem „natywnie wolnej Presty”. Jak wspominałem w moim wpisie inaugurującym na LinkedIn (https://www.linkedin.com/posts/micha%C5%82-sobczak_prestashop-devops-webperformance-share-7424395494283444226-T0-e/), wiele sklepów traci ogromne pieniądze przez błędy, które dla architekta są oczywiste, ale dla biznesu pozostają całkowicie niewidoczne.
Dzisiaj rozkładam na czynniki pierwsze konkretny audyt sklepu (15k+ produktów), który dusił się przy zaledwie 50 użytkownikach online. Wyczyszczenie tych wąskich gardeł pozwoliło nam zejść z TTFB (Time to First Byte) z koszmarnych 2,5 sekundy do zaledwie 300 milisekund. Bez wydawania ani złotówki na mocniejszą infrastrukturę.
1. Zabójcza Sitemap'a w czasie rzeczywistym
Podczas wspomnianego audytu, hosting rozkładał ręce, twierdząc, że maszyna jest w pełni wydajna. Szybki rzut oka w logi i htop ujawnił jednak potężną anomalię: pracownicy Back Office nieświadomie destabilizowali cały front-end dla klientów.
Winowajcą okazał się moduł mapy strony, który został niefortunnie podpięty pod hook aktualizacji produktu (actionProductUpdate).
Co to oznaczało w praktyce? Każde jedno kliknięcie przycisku „Zapisz” podczas edycji ceny, opisu czy stanu magazynowego przez managera w panelu admina uruchamiało proces generowania pliku XML dla wszystkich 15 tysięcy produktów w czasie rzeczywistym.
Skutek: Panel admina „wisiał” przez 30 sekund.
Wszystkie wątki (workerzy) PHP były błyskawicznie utylizowane.
Klienci próbujący w tym samym czasie złożyć zamówienie na froncie odbijali się od ściany z błędem 503.
Rozwiązanie: Całkowite wyrzucenie generowania sitemapy z logiki aplikacji i przeniesienie tego procesu do zadania CRON, uruchamianego raz na dobę o godzinie 3:00 w nocy, kiedy ruch na sklepie jest minimalny.
2. Klasyczny problem N+1 oraz śmieci w bazie danych
Drugim potężnym operatorem opóźnień była baza danych MySQL, która dosłownie krztusiła się przy każdym odświeżeniu strony produktu.
Po pierwsze, włączone były natywne moduły statystyk PrestaShop. Zbieranie analityki bezpośrednio przez silnik sklepu (w bazie danych) to relikt przeszłości, który w dobie GA4 nie ma żadnego biznesowego uzasadnienia. Tabela ps_connections potrafi spuchnąć do gigantycznych rozmiarów, blokując operacje I/O serwera.
Po drugie, na karcie produktu rzeźnię siał moduł typu „Klienci kupili również”. Został napisany w sposób skrajnie nieoptymalny - zamiast jednego, dobrze przygotowanego zapytania z operatorem JOIN (lub IN), programista wrzucił zapytanie SQL do pętli.
Problem N+1 w praktyce: Dla każdego wyświetlanego produktu rekomendowanego, system wykonywał OSOBNE zapytanie do bazy danych o jego szczegóły. Zamiast jednego strzału do MySQL, mieliśmy ich kilkanaście lub kilkadziesiąt przy każdym załadowaniu strony.
Rozwiązanie: Wyłączenie zasobożernych modułów statystyk, wyczyszczenie tabel logów oraz refaktoryzacja kodu modułu rekomendacji, by pobierał paczkę danych jednym zapytaniem. Dodatkowo wdrożyliśmy agresywny cache obiektowy z wykorzystaniem Redis, co niemal całkowicie odcięło bazę danych od powtarzalnych zapytań o konfigurację sklepu i niezmienne cechy produktów.
3. Gdy standardowe UI wysiada: Horror 8 000 kategorii
W e-commerce często spotyka się problem skrajnych wolumenów asocjacji (powiązań danych). Razem z Miłoszem Branewiczem trafiliśmy niedawno na skrajny przypadek inżynieryjny, w którym standardowa struktura PrestaShop po prostu skapitulowała.
Klient posiadał zaawansowaną integrację z zewnętrznym API, która na bazie cech dynamicznie tworzyła i przypisywała kategorie do produktów. Po latach działania systemu, baza zanotowała rekordzistów: jeden produkt potrafił mieć przypisane ponad 8 000 kategorii.
Więcej o architekturze tego problemu i o tym, jak standardowe inputy przestają wystarczać, możecie przeczytać w moim dedykowanym case study na LinkedIn (https://www.linkedin.com/posts/micha%C5%82-sobczak_prestashop-ecommerce-refactoring-share-7425086196017467392-9U9n/).
W czym tkwił problem wydajnościowy? Próba edycji takiego produktu w Back Office była niemożliwa. Domyślne renderowanie pełnego drzewa kategorii (w formie gigantycznej struktury checkboxów) zapychało pamięć przeglądarki i serwera. Podkręcanie memory_limit do absurdalnych wartości pozwalało co prawda otworzyć kartę, ale przy próbę zapisu serwer i tak sypał błędami timeoutu.
Rozwiązanie: Zamiast walczyć z natywnym komponentem drzewa Presty, postanowiliśmy je całkowicie wyciąć z edycji produktu i napisać mechanizm na nowo:
Usunęliśmy domyślne renderowanie drzewa w Back Office.
Wdrożyliśmy pełną asynchroniczność (AJAX) i paginację (kategorie ładują się paczkami po kilkadziesiąt sztuk w miarę scrollowania, a nie 8000 na raz).
Dodaliśmy wyszukiwarkę kategorii „live”.
Każde przypięcie, odpięcie czy zmiana kategorii głównej dzieje się w tle (XHR) w ułamku sekundy, natychmiast po kliknięciu.
Dzięki temu karta produktu ładuje się błyskawicznie, niezależnie od skali powiązań, a front-end i wyszukiwarka dla klientów działają bez zmian.
4. Wyjątek od reguły: Kiedy system MUSI działać wolniej?
Jako inżynier zazwyczaj toczę bezwzględną wojnę o każdą milisekundę. Istnieją jednak sytuacje, w których celowe opóźnienie odpowiedzi serwera jest jedyną drogą do ochrony biznesu. Doskonale przykładem jest niedawna łatka bezpieczeństwa w PrestaShop (wersja 9.0.3), która łata lukę typu Time-Based Enumeration.
Jak szczegółowo opisałem w moim wpisie o cyberbezpieczeństwie (https://www.linkedin.com/posts/micha%C5%82-sobczak_prestashop-cybersecurity-ecommerce-share-7426903135241179136-hJWB/), hakerzy potrafią wykorzystać fakt, że serwer jest... zbyt szybki i zbyt szczery. Przy próbie logowania bot podaje adres e-mail:
Jeśli mail NIE istnieje w bazie, Presta błyskawicznie zwracała błąd (np. w ~20ms).
Jeśli mail ISTNIEJE, system musiał pobrać hash hasła i uruchomić zasobożerną operację kryptograficzną, by porównać go z wpisanym ciągiem znaków. To trwało znacznie dłużej (np. ~300ms).
Dla bota ta różnica 280ms to jasny komunikat: „Ten mail istnieje w bazie, dopisz go do listy celów do ataku typu Brute-Force”.
Co robi nowa łatka? Wprowadza tzw. Constant Time Operation. Jeśli użytkownik nie istnieje, system celowo wykonuje „fałszywe” kalkulacje procesora tylko po to, by zmarnować czas i wyrównać odpowiedź serwera dla obu scenariuszy do stałych ~300ms. Serwer celowo działa wolniej, by chronić prywatność danych Twoich klientów.
Wnioski: Najpierw profiler, potem zakupy
Zanim zatwierdzisz kolejną wyższą fakturę za infrastrukturę hostingową, zrób krok w tył. Sprawdź htop, logi profilera (np. Tideways czy natywny profil PrestaShop) i zobacz, gdzie system faktycznie traci czas.
Pamiętaj jednak, że oficjalne poprawki i czysty rdzeń to dopiero fundament bezpieczeństwa i wydajności. Jeśli Twój e-commerce działa w oparciu o 50 losowych modułów od nieznanych autorów zakupionych na przestrzeni lat, to łatanie samego silnika przypomina montowanie pancernych drzwi w domu, w którym zostawiłeś otwarte okna.
Twój sklep potrzebuje stabilizacji, ochrony przed pikami sprzedażowymi i czyszczenia długu technologicznego? W mojej codziennej praktyce inżynieryjnej pod szyldem Web Berserker nie zajmuję się „wyklikiwaniem” gotowych szablonów. Podchodzę do architektury e-commerce ze ścisłą surowością. Skontaktuj się ze mną bezpośrednio przez formularz na stronie, a w ramach profesjonalnej opieki SLA w pierwszej kolejności wykonam twardy, strukturalny audyt Twojego kodu