{"id":1589,"date":"2026-04-23T22:00:44","date_gmt":"2026-04-23T22:00:44","guid":{"rendered":"https:\/\/news.jurskitech.pl\/blog\/uncategorized\/zabojcze-polaczenie-slaby-backend-i-przeciazony-frontend\/"},"modified":"2026-04-23T22:00:44","modified_gmt":"2026-04-23T22:00:44","slug":"zabojcze-polaczenie-slaby-backend-i-przeciazony-frontend","status":"publish","type":"post","link":"https:\/\/news.jurskitech.pl\/blog\/warto-wiedziec\/zabojcze-polaczenie-slaby-backend-i-przeciazony-frontend\/","title":{"rendered":"Zab\u00f3jcze po\u0142\u0105czenie: s\u0142aby backend i przeci\u0105\u017cony frontend"},"content":{"rendered":"<h2 id=\"wstp\">Wst\u0119p<\/h2>\n<p>W ostatnich latach obserwuj\u0119 ciekawy trend. Firmy prze\u015bcigaj\u0105 si\u0119 w implementacji nowoczesnych framework\u00f3w frontendowych. React, Next.js, Vue \u2013 ka\u017cdy chce mie\u0107 szybki, interaktywny interfejs. Tymczasem najwi\u0119kszym w\u0105skim gard\u0142em wydajno\u015bci nie jest frontend, tylko backend. Mo\u017cesz mie\u0107 najl\u017cejszy interfejs \u015bwiata, ale je\u015bli API odpowiada w 3 sekundy, u\u017cytkownik i tak poczuje frustracj\u0119.<\/p>\n<p>W tym artykule poka\u017c\u0119 trzy realne scenariusze, w kt\u00f3rych s\u0142aby backend niszczy wysi\u0142ki frontendowc\u00f3w. S\u0105 to sytuacje z \u017cycia wzi\u0119te \u2013 widzia\u0142em je u klient\u00f3w, kt\u00f3rzy przyszli z problemem \u201estrona jest wolna\u201d, a po audycie okazywa\u0142o si\u0119, \u017ce to nie wina kodu po stronie klienta.<\/p>\n<h2 id=\"1n1zapytacichyzabjcawydajnoci\">1. N+1 zapyta\u0144 \u2013 cichy zab\u00f3jca wydajno\u015bci<\/h2>\n<p>Zaczniemy od klasyka. Wyobra\u017a sobie sklep e-commerce, kt\u00f3ry wy\u015bwietla list\u0119 produkt\u00f3w. Na froncie pobierasz list\u0119 20 produkt\u00f3w, a nast\u0119pnie dla ka\u017cdego z nich wykonujesz osobne zapytanie o cen\u0119, stan magazynowy, opinie i zdj\u0119cia. Efekt? 1 + 4*20 = 81 zapyta\u0144 do bazy danych dla jednego widoku. Przy 1000 odwiedzaj\u0105cych dziennie to 81 000 zapyta\u0144 \u2013 pot\u0119\u017cne obci\u0105\u017cenie.<\/p>\n<p>Najgorsze jest to, \u017ce programi\u015bci frontendowi cz\u0119sto nie widz\u0105 tego problemu. Narz\u0119dzia deweloperskie w przegl\u0105darkach pokazuj\u0105 tylko czas odpowiedzi API, a nie to, ile zapyta\u0144 generuje backend. Dlatego klient m\u00f3wi: \u201efrontend dzia\u0142a wolno\u201d, podczas gdy w rzeczywisto\u015bci to backend robi za du\u017co pracy.<\/p>\n<p><strong>Przyk\u0142ad z \u017cycia:<\/strong> Klient prowadz\u0105cy sklep z odzie\u017c\u0105. Strona g\u0142\u00f3wna \u0142adowa\u0142a si\u0119 8 sekund. Okaza\u0142o si\u0119, \u017ce backend dla ka\u017cdego produktu pobiera\u0142 osobno dane z trzech tabel. Po dodaniu eager loadingu (czyli pobraniu wszystkich danych w jednym zapytaniu) czas spad\u0142 do 1,2 sekundy. Zero zmian w frontendzie.<\/p>\n<p><strong>Co zrobi\u0107?<\/strong> Audytuj zapytania do bazy. Narz\u0119dzia jak Django Debug Toolbar czy Rails Panel pokazuj\u0105 liczb\u0119 zapyta\u0144 na stron\u0119. Cel to poni\u017cej 10 zapyta\u0144 dla typowego widoku. U\u017cywaj mechanizm\u00f3w N+1 detector w ORM-ach.<\/p>\n<h2 id=\"2brakcacheowaniaapipaciszkadymrequestem\">2. Brak cache\u2019owania API \u2013 p\u0142acisz ka\u017cdym requestem<\/h2>\n<p>Drugi cz\u0119sty grzech to brak cache\u2019owania odpowiedzi API. Nawet je\u015bli backend jest szybki, to generowanie tej samej odpowiedzi dla ka\u017cdego u\u017cytkownika jest marnotrawstwem. Lista produkt\u00f3w, kategorie, stopka \u2013 to dane, kt\u00f3re zmieniaj\u0105 si\u0119 rzadko. A tymczasem wielu programist\u00f3w generuje je na nowo przy ka\u017cdym \u017c\u0105daniu.<\/p>\n<p>Problem polega na tym, \u017ce frontendowcy cz\u0119sto projektuj\u0105 interfejs tak, by pobiera\u0107 dane w czasie rzeczywistym. To \u015bwietne dla komponent\u00f3w dynamicznych, ale oznacza, \u017ce backend musi obs\u0142u\u017cy\u0107 setki zapyta\u0144 na sekund\u0119 dla tych samych danych.<\/p>\n<p><strong>Scenariusz:<\/strong> Strona bloga z najnowszymi wpisami. Ka\u017cdy odwiedzaj\u0105cy pobiera list\u0119 artyku\u0142\u00f3w. Je\u015bli nie ma cache\u2019a, serwer przy 1000 u\u017cytkownikach generuje 1000 zapyta\u0144 do bazy. Z cache\u2019em Redis lub Varnish \u2013 tylko pierwsze zapytanie idzie do bazy, reszta z pami\u0119ci podr\u0119cznej. R\u00f3\u017cnica w czasie odpowiedzi: 300 ms vs 5 ms.<\/p>\n<p><strong>Realny przypadek:<\/strong> Firma z bran\u017cy turystycznej. Ich backend generowa\u0142 list\u0119 wycieczek na podstawie skomplikowanych kalkulacji. Czas odpowiedzi API wynosi\u0142 \u015brednio 1,2 sekundy. Po wprowadzeniu cache\u2019a z okresem wa\u017cno\u015bci 5 minut \u2013 spad\u0142 do 15 ms. Wzrost konwersji o 12% tylko dlatego, \u017ce lista wycieczek \u0142adowa\u0142a si\u0119 b\u0142yskawicznie.<\/p>\n<p><strong>Wskaz\u00f3wka:<\/strong> Zidentyfikuj endpointy, kt\u00f3re zwracaj\u0105 dane rzadko zmieniaj\u0105ce si\u0119. Dodaj cache na poziomie aplikacji (Redis, Memcached) lub u\u017cyj CDN z cache\u2019owaniem API. Ustaw odpowiednie nag\u0142\u00f3wki Cache-Control.<\/p>\n<h2 id=\"3zbytcikieodpowiedziapifrontendniemaszans\">3. Zbyt ci\u0119\u017ckie odpowiedzi API \u2013 frontend nie ma szans<\/h2>\n<p>Trzeci problem to przesy\u0142anie zbyt du\u017cych ilo\u015bci danych. Frontend cz\u0119sto potrzebuje tylko kilku p\u00f3l z modelu, a backend wysy\u0142a ca\u0142y obiekt wraz z relacjami, histori\u0105 zmian i metadanymi. Im wi\u0119ksza odpowied\u017a, tym d\u0142u\u017cszy czas transferu, a na s\u0142abszych \u0142\u0105czach \u2013 wi\u0119ksze ryzyko b\u0142\u0119du.<\/p>\n<p><strong>Przyk\u0142ad:<\/strong> Aplikacja do zarz\u0105dzania projektami. Endpoint GET \/tasks zwraca dla ka\u017cdego zadania: ID, tytu\u0142, opis, osob\u0119 przypisan\u0105, histori\u0119 zmian, komentarze, za\u0142\u0105czniki. W odpowiedzi jest 15 KB na zadanie. Przy 100 zadaniach to 1,5 MB. Dla u\u017cytkownika na LTE to mo\u017ce by\u0107 2-3 sekundy samego transferu.<\/p>\n<p>Tymczasem frontend potrzebuje tylko ID, tytu\u0142u i osoby przypisanej do wy\u015bwietlenia listy. Reszta danych jest niepotrzebna i obci\u0105\u017ca zar\u00f3wno backend, jak i frontend.<\/p>\n<p><strong>Rozwi\u0105zanie:<\/strong> Stosuj GraphQL lub przynajmniej dedykowane endpointy z mo\u017cliwo\u015bci\u0105 wyboru p\u00f3l (sparse fieldsets w REST). Dzi\u0119ki temu frontend decyduje, co pobiera\u0107. Mo\u017cna te\u017c doda\u0107 paginacj\u0119 i filtrowanie po stronie backendu \u2013 nie pobieraj wszystkich rekord\u00f3w, je\u015bli u\u017cytkownik ogl\u0105da tylko pierwsze 10.<\/p>\n<p><strong>Przypadek z \u017cycia:<\/strong> Startup SaaS oferuj\u0105cy dashboard. Ich g\u0142\u00f3wny widok \u0142\u0105czy\u0142 dane z 6 r\u00f3\u017cnych endpoint\u00f3w, ka\u017cdy zwraca\u0142 pe\u0142ne obiekty. Po wprowadzeniu dedykowanego endpointu zwracaj\u0105cego tylko potrzebne pola (i z\u0142\u0105czonego w jedno zapytanie), czas \u0142adowania strony spad\u0142 z 5,2 sekundy do 0,8 sekundy. Wzrost retencji u\u017cytkownik\u00f3w o 15%.<\/p>\n<h2 id=\"podsumowanie\">Podsumowanie<\/h2>\n<p>S\u0142aby backend to najszybszy spos\u00f3b, aby zniszczy\u0107 wra\u017cenia u\u017cytkownika, nawet je\u015bli masz najlepszy frontend na \u015bwiecie. Zanim zaczniesz optymalizowa\u0107 kod po stronie klienta, sprawd\u017a fundamenty:<\/p>\n<ul>\n<li>Czy API odpowiada szybko?<\/li>\n<li>Czy u\u017cywa cache?<\/li>\n<li>Czy zwraca tylko potrzebne dane?<\/li>\n<\/ul>\n<p>Bo je\u015bli backend jest w\u0105skim gard\u0142em, \u017caden frontend tego nie ukryje.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wst\u0119p W ostatnich latach obserwuj\u0119 ciekawy trend. Firmy prze\u015bcigaj\u0105 si\u0119 w implementacji nowoczesnych framework\u00f3w frontendowych. React, Next.js, Vue \u2013 ka\u017cdy chce mie\u0107 szybki, interaktywny interfejs. Tymczasem najwi\u0119kszym w\u0105skim gard\u0142em wydajno\u015bci nie jest frontend, tylko backend. Mo\u017cesz mie\u0107 najl\u017cejszy interfejs \u015bwiata, ale je\u015bli API odpowiada w 3 sekundy, u\u017cytkownik i tak poczuje frustracj\u0119. W tym artykule<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[10,265,121,188,26],"class_list":["post-1589","post","type-post","status-publish","format-standard","hentry","category-warto-wiedziec","tag-ai-w-e-commerce","tag-architektura-frontendu","tag-backend","tag-optymalizacja-infrastruktury","tag-wydajnosc"],"_links":{"self":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/1589","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/comments?post=1589"}],"version-history":[{"count":0,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/1589\/revisions"}],"wp:attachment":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/media?parent=1589"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/categories?post=1589"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/tags?post=1589"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}