{"id":2166,"date":"2026-06-17T15:00:36","date_gmt":"2026-06-17T15:00:36","guid":{"rendered":"https:\/\/news.jurskitech.pl\/blog\/uncategorized\/czy-twoj-saas-traci-na-zbyt-wolnych-odpowiedziach-api-3-lekcje-z-backendu\/"},"modified":"2026-06-17T15:00:36","modified_gmt":"2026-06-17T15:00:36","slug":"czy-twoj-saas-traci-na-zbyt-wolnych-odpowiedziach-api-3-lekcje-z-backendu","status":"publish","type":"post","link":"https:\/\/news.jurskitech.pl\/blog\/warto-wiedziec\/czy-twoj-saas-traci-na-zbyt-wolnych-odpowiedziach-api-3-lekcje-z-backendu\/","title":{"rendered":"Czy Tw\u00f3j SaaS traci na zbyt wolnych odpowiedziach API? 3 lekcje z backendu"},"content":{"rendered":"<h1 id=\"czytwjsaastracinazbytwolnychodpowiedziachapi3lekcjezbackendu\">Czy Tw\u00f3j SaaS traci na zbyt wolnych odpowiedziach API? 3 lekcje z backendu<\/h1>\n<p>Pracuj\u0119 z SaaS-ami od ponad dekady. I powiem Ci wprost: wi\u0119kszo\u015b\u0107 firm nie zdaje sobie sprawy, \u017ce ich API jest w\u0105skim gard\u0142em. Nie chodzi o to, \u017ce serwery padaj\u0105 \u2013 chodzi o to, \u017ce odpowiedzi przychodz\u0105 w 400 ms zamiast 50 ms. Brzmi niewinnie? Dla u\u017cytkownika to wieczno\u015b\u0107. Dla Twoich KPI \u2013 katastrofa.<\/p>\n<p>W jednym z projekt\u00f3w, kt\u00f3ry audytowa\u0142em, firma traci\u0142a 20% u\u017cytkownik\u00f3w w trakcie onboardingu. Pow\u00f3d? API zwraca\u0142o list\u0119 konfiguracji w 3 sekundy. Po optymalizacji do 100 ms wska\u017anik konwersji wzr\u00f3s\u0142 o 12%. Zero zmian w UI, tylko backend.<\/p>\n<p>Oto trzy lekcje, kt\u00f3re wynios\u0142em z realnych wdro\u017ce\u0144.<\/p>\n<h2 id=\"1n1queriescichyzabjcawydajnoci\">1. N+1 queries \u2013 cichy zab\u00f3jca wydajno\u015bci<\/h2>\n<p>ORM-y jak ActiveRecord czy Hibernate s\u0105 wygodne, ale maj\u0105 jedn\u0105 pu\u0142apk\u0119: generuj\u0105 zapytania w p\u0119tli. Je\u015bli pobierasz list\u0119 zam\u00f3wie\u0144, a potem dla ka\u017cdego zam\u00f3wienia pobierasz szczeg\u00f3\u0142y \u2013 boom, masz N+1 zapyta\u0144.<\/p>\n<p><strong>Przyk\u0142ad z \u017cycia:<\/strong><br \/>\nKlient mia\u0142 endpoint <code>\/orders<\/code> kt\u00f3ry dla 100 zam\u00f3wie\u0144 wykonywa\u0142 101 zapyta\u0144 do bazy. Ka\u017cde zapytanie to 5 ms, wi\u0119c \u0142\u0105cznie ~500 ms. Po dodaniu eager loading i optymalizacji indeks\u00f3w spad\u0142o do 15 ms. R\u00f3\u017cnica? 30x szybciej.<\/p>\n<p><strong>Co robi\u0107?<\/strong><\/p>\n<ul>\n<li>U\u017cywaj eager loading (JOIN-y) zamiast leniwego \u0142adowania.<\/li>\n<li>Monitoruj liczb\u0119 zapyta\u0144 na endpoint \u2013 je\u015bli ro\u015bnie liniowo z danymi, masz problem.<\/li>\n<li>Rozwa\u017c u\u017cycie GraphQL, je\u015bli klienci cz\u0119sto \u017c\u0105daj\u0105 r\u00f3\u017cnych zestaw\u00f3w danych.<\/li>\n<\/ul>\n<h2 id=\"2brakcacheowaniaodpowiedziprzepalaszmocobliczeniow\">2. Brak cache&#8217;owania odpowiedzi \u2013 przepalasz moc obliczeniow\u0105<\/h2>\n<p>Wielu developer\u00f3w my\u015bli: \u201ePo co cache\u2019owa\u0107, skoro baza jest szybka?\u201d. Ale baza nie jest szybka, gdy zapytanie dotyczy 50 tabel. A ju\u017c na pewno nie jest szybka, gdy to samo zapytanie wykonuje 1000 u\u017cytkownik\u00f3w na sekund\u0119.<\/p>\n<p><strong>Lekcja z projektu e-commerce:<\/strong><br \/>\nEndpoint <code>\/products\/popular<\/code> by\u0142 wo\u0142any przez ka\u017cd\u0105 stron\u0119 g\u0142\u00f3wn\u0105. Bez cache\u2019owania \u2013 200 ms odpowiedzi. Z Redisem i TTL 30 sekund \u2013 5 ms. Odci\u0105\u017cyli\u015bmy baz\u0119 o 90% zapyta\u0144.<\/p>\n<p><strong>Strategia:<\/strong><\/p>\n<ul>\n<li>Cache\u2019uj odpowiedzi, kt\u00f3re s\u0105 rzadko zmieniane (lista kategorii, konfiguracje).<\/li>\n<li>U\u017cywaj cache inwalidacji opartej na zdarzeniach \u2013 np. webhook gdy produkt si\u0119 zmienia.<\/li>\n<li>Dla danych u\u017cytkownika rozwa\u017c cache per-user z kr\u00f3tkim TTL.<\/li>\n<\/ul>\n<h2 id=\"3zbytduepayloadywysyaszniepotrzebnedane\">3. Zbyt du\u017ce payloady \u2013 wysy\u0142asz niepotrzebne dane<\/h2>\n<p>Standardowy b\u0142\u0105d: endpoint zwraca pe\u0142ny obiekt z 50 polami, a klient potrzebuje tylko 3. To nie tylko marnuje przepustowo\u015b\u0107, ale te\u017c wyd\u0142u\u017ca czas serializacji i transferu.<\/p>\n<p><strong>Obserwacja z pola:<\/strong><br \/>\nW jednym SaaS endpoint <code>\/user\/profile<\/code> zwraca\u0142 ca\u0142y rekord u\u017cytkownika (avatar w base64, histori\u0119 logowa\u0144, preferencje). Payload wa\u017cy\u0142 300 KB. Po wprowadzeniu wersjonowania API i dedykowanych p\u00f3l \u2013 spad\u0142 do 5 KB. Klient mobilny odetchn\u0105\u0142.<\/p>\n<p><strong>Jak to naprawi\u0107?<\/strong><\/p>\n<ul>\n<li>U\u017cywaj p\u00f3l opcjonalnych (sparse fieldsets) \u2013 klient m\u00f3wi, co chce.<\/li>\n<li>Paginuj listy \u2013 nikt nie potrzebuje 10 000 rekord\u00f3w na raz.<\/li>\n<li>Kompresuj odpowiedzi (gzip, brotli).<\/li>\n<\/ul>\n<h2 id=\"podsumowanie\">Podsumowanie<\/h2>\n<p>Wolne API to nie problem serwer\u00f3w \u2013 to problem architektury. Zanim kupisz kolejn\u0105 instancj\u0119, sp\u00f3jrz na zapytania, cache i payload. Te trzy rzeczy cz\u0119sto daj\u0105 10x popraw\u0119 bez ani jednego nowego serwera.<\/p>\n<p>A je\u015bli potrzebujesz pomocy w audycie backendu \u2013 wiemy, jak to zrobi\u0107 bez marketingowego lania wody.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Czy Tw\u00f3j SaaS traci na zbyt wolnych odpowiedziach API? 3 lekcje z backendu Pracuj\u0119 z SaaS-ami od ponad dekady. I powiem Ci wprost: wi\u0119kszo\u015b\u0107 firm nie zdaje sobie sprawy, \u017ce ich API jest w\u0105skim gard\u0142em. Nie chodzi o to, \u017ce serwery padaj\u0105 \u2013 chodzi o to, \u017ce odpowiedzi przychodz\u0105 w 400 ms zamiast 50 ms.<\/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":[699,556,617,431],"class_list":["post-2166","post","type-post","status-publish","format-standard","hentry","category-warto-wiedziec","tag-api-gateway","tag-architektura-backend","tag-b2b-saas","tag-optymalizacja-wydajnosci"],"_links":{"self":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2166","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=2166"}],"version-history":[{"count":0,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2166\/revisions"}],"wp:attachment":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/media?parent=2166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/categories?post=2166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/tags?post=2166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}