Rosnące wymagania użytkowników sprawiają, że witryny internetowe są coraz bardziej rozbudowane, a każda dodatkowa funkcja generuje nowe zapytania do serwera. Liczba requestów HTTP szybko rośnie: osobno ładowane są pliki CSS, skrypty JS, grafiki, fonty, dane z API. To wszystko wpływa na czas ładowania strony, obciążenie serwera i koszty utrzymania. Celem tego artykułu jest pokazanie technik, które pozwalają zmniejszyć liczbę requestów, nie rezygnując z funkcjonalności, a czasem wręcz ją poprawiając.
Dlaczego liczba requestów ma tak duże znaczenie
Każdy dodatkowy request HTTP to opóźnienie: zestawianie połączenia, negocjacja protokołu, nagłówki, ewentualne przekierowania. Nawet przy szybkim łączu suma wielu małych opóźnień powoduje wyraźne spowolnienie. W kontekście UX liczy się to, co użytkownik odczuwa: sekundy czekania, zanim strona stanie się interaktywna, wpływają na współczynnik odrzuceń, konwersje i zaufanie do marki. Wydajność staje się więc kluczowym elementem konkurencji między serwisami.
Równie ważna jest perspektywa serwerowa. Wysoka liczba requestów zwiększa obciążenie serwerów aplikacyjnych, serwerów plików, CDN oraz baz danych. Więcej żądań to większe ryzyko wąskich gardeł, konieczność skalowania infrastruktury i wyższe koszty. Nawet jeśli pojedyncze żądanie jest lekkie, ich kumulacja przy dużym ruchu potrafi doprowadzić do realnych problemów z dostępnością serwisu.
Trzeba też pamiętać o urządzeniach mobilnych i sieciach o wysokich opóźnieniach. Użytkownik w podróży, korzystający z sieci komórkowej, szczególnie odczuwa koszt wielu małych zasobów ładowanych sekwencyjnie. Liczba requestów przekłada się na zużycie baterii, transfer danych i komfort korzystania z aplikacji webowej. Stąd tak duży nacisk na techniki optymalizacji HTTP, w tym redukcję zbędnych żądań.
Istotne jest rozróżnienie: celem nie jest jedynie zmniejszenie rozmiaru danych, ale także ograniczenie samej liczby odwołań. Można mieć stosunkowo lekką stronę, która jednak generuje kilkaset requestów, i przez to działa ospale. Z drugiej strony strona o większej objętości, ale dobrze zoptymalizowanej strukturze żądań, może subiektywnie działać szybciej. Optymalna strategia łączy obie perspektywy: minimalizację liczby requestów oraz rozmiaru zasobów.
Łączenie zasobów: CSS, JS i fonty
Jednym z najbardziej oczywistych, ale ciągle aktualnych sposobów redukcji liczby requestów jest łączenie plików statycznych. Zamiast ładować kilkanaście osobnych arkuszy stylów i skryptów, generujemy jeden lub kilka logicznie pogrupowanych plików. Łączenie CSS i JS nie tylko zmniejsza liczbę żądań, lecz także ułatwia kontrolę nad kolejnością ładowania oraz cache’owaniem.
Tradycyjnie wykonywało się to w procesie build przy pomocy narzędzi takich jak Webpack, Rollup, Parcel czy Vite. Współczesne bundlery oferują tree shaking, kod dzielony na bundle per widok lub moduł, minifikację i kompresję. Zamiast wielu małych skryptów związanych z różnymi komponentami interfejsu można wygenerować kilka pakietów: główny dla krytycznej funkcjonalności oraz dodatkowe bundle ładowane później lub na żądanie. W ten sposób liczbę requestów redukujemy bez utraty elastyczności logiki biznesowej.
W przypadku CSS warto rozważyć wydzielenie krytycznych stylów do sekcji inline (critical CSS), a resztę ładować w jednym zoptymalizowanym pliku cache’owanym długoterminowo. Dzięki temu pierwsze renderowanie widoku może nastąpić bez konieczności wysyłania dodatkowych żądań, a kolejne podstrony korzystają już z tego samego, dobrze cache’owanego zasobu. To połączenie minimalizacji requestów z dbałością o rendering above the fold.
Fonty to kolejny obszar, w którym często pojawia się nadmiar żądań. Każda wariacja kroju i grubości to osobny plik, a w skrajnych przypadkach strona ładuje kilkanaście plików fontów, z których realnie wykorzystywana jest niewielka część. Optymalizacja polega na ograniczeniu liczby rodzin i wariantów, stosowaniu podzbiorów znaków (subsetów) oraz łączeniu wariantów w jednym pliku, jeśli format na to pozwala. Warto też korzystać z nowoczesnych formatów jak WOFF2, aby zredukować wielkość pobieranych danych.
W architekturach modułowych i mikrofrontendowych łatwo o sytuację, w której każdy moduł wprowadza własne pakiety JS i CSS. Bez spójnej strategii bundlingu prowadzi to do duplikacji kodu i nadmiarowych requestów. Rozwiązaniem jest współdzielona konfiguracja narzędzi build, centralna kontrola zależności oraz analiza grafu importów. Pomaga także regularny audyt narzędziem typu Lighthouse czy WebPageTest, aby identyfikować niepotrzebne żądania i usuwać zbędne pliki z produkcji.
Optymalizacja grafiki i sprytne zarządzanie obrazami
Obrazy stanowią zwykle największy udział w ruchu, a także generują wiele osobnych requestów. Pierwszy krok to zmiana formatu. Przejście z JPEG/PNG na nowoczesne formaty takie jak WebP czy AVIF pozwala znacząco zmniejszyć rozmiar pliku, co skraca czas pobierania. Jednak liczba requestów pozostaje taka sama, jeśli nadal każdy element graficzny to osobny zasób. Stąd pomysły na techniki łączenia lub generowania obrazów dynamicznie.
W przypadku ikon i prostych grafik wektorowych bardzo skuteczne są sprite’y SVG lub fonty ikon. Zamiast kilkudziesięciu małych plików PNG ładowany jest jeden skompresowany zasób, z którego interfejs odwołuje się do konkretnych symboli. Nowoczesne przeglądarki bardzo dobrze radzą sobie z SVG, a możliwość skalowania bez utraty jakości poprawia odbiór wizualny. To klasyczny przykład, gdzie redukujemy liczbę requestów, jednocześnie podnosząc elastyczność wyglądu.
Lazy loading jest techniką zorientowaną bardziej na rozłożenie obciążenia w czasie niż na globalne zmniejszenie sumy requestów, ale ma ogromne znaczenie z punktu widzenia pierwszego wrażenia. Wiele grafik poniżej linii przewijania nie powinno być ładowanych natychmiast. Dopiero po zbliżeniu się użytkownika do danej sekcji wysyłane są dodatkowe zapytania. Implementacja z użyciem atrybutu loading=lazy lub biblioteki Intersection Observer pozwala obniżyć liczbę requestów w krytycznej fazie ładowania strony.
Istotnym elementem jest też odpowiednie kadrowanie i generowanie wielu rozdzielczości. Zamiast ładować ten sam duży plik dla wszystkich urządzeń, stosuje się źródła responsywne (srcset, sizes) albo dedykowany serwis przetwarzający obrazy. Choć w tle generowane są dodatkowe zasoby, z perspektywy pojedynczej sesji użytkownika liczba i rozmiar requestów są zoptymalizowane. Kluczowe jest tu połączenie CDN z funkcjami transformacji obrazów on the fly i agresywnym cache’owaniem.
Dobrym nawykiem jest okresowe czyszczenie nieużywanych grafik. Projekty rozwijane od wielu lat gromadzą setki historycznych plików, które nigdy nie są już referencjonowane w kodzie, ale wciąż znajdują się na serwerze lub w repozytorium. Analiza logów serwera oraz automatyczne skanery powiązań statycznych pozwalają usuwać martwe zasoby. Dzięki temu spada ryzyko przypadkowego ładowania nieaktualnych grafik przez stary kod lub komponenty pozostawione w interfejsie.
Cache, CDN i zarządzanie nagłówkami HTTP
Choć cache nie zmienia bezpośrednio liczby requestów wysyłanych przez przeglądarkę, decyduje o tym, które z nich zakończą się realnym pobraniem danych z serwera. Odpowiednio skonfigurowane nagłówki Cache-Control, ETag, Expires i Last-Modified sprawiają, że wiele zasobów jest odświeżanych rzadko, a przeglądarka może korzystać z lokalnej kopii. W praktyce przekłada się to na poczucie szybkości działania i mniejsze obciążenie infrastruktury.
Długoterminowe cache’owanie statycznych plików wymaga strategii wersjonowania. Najczęściej stosuje się fingerprinting nazw plików, na przykład poprzez dodawanie skrótu hash do nazwy. Gdy treść pliku CSS lub JS się zmienia, generowany jest nowy hash, a przeglądarka pobiera świeżą wersję. Dopóki plik jest identyczny, może być przechowywany w cache przez bardzo długi czas. W ten sposób rzadziej zmieniane zasoby generują pojedynczy request na wiele sesji, a nie za każdym odświeżeniem strony.
Sieci dostarczania treści (CDN) pozwalają przenieść obsługę statycznych plików bliżej użytkownika, skracając czas odpowiedzi i odciążając serwer aplikacyjny. To szczególnie ważne przy globalnym ruchu. Z punktu widzenia liczby requestów kluczowe jest jednak to, że część z nich jest obsługiwana całkowicie na brzegu sieci, bez angażowania głównego systemu. CDN może też dostarczać funkcje optymalizacji obrazów, minifikacji i kompresji gzip lub brotli, co dodatkowo poprawia performance.
Interesującą techniką jest cache’owanie dynamicznych odpowiedzi API po stronie serwera lub na poziomie edge w CDN. Jeśli wiele użytkowników pobiera te same dane (np. popularne listy produktów, artykuły, rankingi), nie ma potrzeby, aby każde zapytanie trafiało do bazy danych. Krótkotrwały cache z wygasaniem na poziomie minut czy nawet sekund potrafi zastąpić setki requestów do warstwy aplikacyjnej jednym odświeżeniem danych. Odpowiednio dobrana polityka TTL i mechanizmy invalidacji pozwalają zachować aktualność treści.
Nie można zapominać o nagłówkach związanych z prefetch i preconnect. Pozwalają one przeglądarce wcześniej nawiązać połączenie lub przygotować się na przyszłe żądania, zanim użytkownik faktycznie ich zażąda. Choć nominalna liczba requestów nie ulega zmianie, subiektywne poczucie szybkości jest lepsze, a same requesty są efektywniej rozłożone w czasie. To uzupełniający element strategii, którego nie należy traktować jako zamiennika dla realnej redukcji zbędnych żądań.
Kompresja danych i minimalizacja payloadu
Redukcja liczby requestów powinna iść w parze z ograniczaniem objętości danych przesyłanych w każdym z nich. Naturalnym narzędziem jest kompresja na poziomie HTTP, w szczególności gzip oraz brotli. Serwer wysyła skompresowaną odpowiedź, którą przeglądarka rozpakowuje. Dotyczy to nie tylko HTML, CSS i JS, ale także wielu innych formatów tekstowych, w tym JSON, XML i dane API. Szczególnie przydatne jest to przy rozbudowanych odpowiedziach, które zawierają wiele nadmiarowych informacji.
Przy interfejsach SPA, gdzie logika klienta jest rozbudowana, istotne staje się ograniczenie rozmiaru głównego pakietu JS. Tree shaking, usuwanie nieużywanego kodu, rezygnacja z ciężkich bibliotek na rzecz lżejszych alternatyw – wszystko to sprawia, że każdy request staje się mniej kosztowny. Wraz z tym warto starannie projektować kontrakty API, eliminując powielone pola, nadmiarowe metadane i niepotrzebnie zagnieżdżone struktury. Mniejsze odpowiedzi oznaczają krótszy czas transferu, a zatem większą efektywność.
W przypadku danych tekstowych ważna jest również normalizacja i ponowne wykorzystanie struktur. Zamiast przesyłać te same informacje w wielu miejscach każdej odpowiedzi, lepiej odesłać je raz i referencjonować identyfikatorami. Ten wzorzec bywa stosowany w API inspirowanych JSON:API czy GraphQL, gdzie dane są lepiej zorganizowane i unikają zduplikowanych wpisów. Efekt to mniejszy rozmiar payloadu przy tej samej funkcjonalności i treści.
Należy też kontrolować liczbę żądań generowanych przez biblioteki zewnętrzne: systemy analityczne, chaty, widgety społecznościowe, menedżery tagów. Nierzadko pojedynczy skrypt zewnętrzny wprowadza kilka kolejnych requestów: pobiera własne zależności, ładuje dodatkowe zasoby, wysyła dane telemetryczne. Analiza faktycznego wpływu takiego komponentu na cele biznesowe bywa zaskakująca. Część integracji można uprościć, opóźnić w czasie albo całkowicie usunąć bez utraty kluczowej funkcjonalności strony.
Ograniczanie nadmiarowych zapytań do API i bazy danych
Nowoczesne aplikacje webowe intensywnie komunikują się z backendem poprzez API. Lista produktów, filtry, komentarze, stan koszyka – wszystko to często realizowane jest jako osobne endpointy. Łatwo doprowadzić do sytuacji, w której jedna podstrona wysyła kilkanaście lub kilkadziesiąt żądań API, z których część zawiera bardzo podobne dane. Oprócz rosnącej liczby requestów rośnie także obciążenie bazy danych i logiki aplikacyjnej.
Jedną z technik jest agregacja zapytań. Zamiast czterech endpointów, z których każdy zwraca wąski wycinek informacji, projektuje się jeden bardziej kompletny, zwracający dane potrzebne do całego widoku. Wymaga to starannego przemyślenia kontraktów, ale redukuje liczbę żądań potrzebnych do wyrenderowania strony. Graficznie można to porównać do przejścia od modelu N+1 w bazach danych do pojedynczego, bogatszego zapytania.
Innym podejściem jest stosowanie GraphQL lub podobnych technologii, które pozwalają klientowi precyzyjnie określić, jakich pól potrzebuje. Zamiast kilku endpointów REST można mieć jedno elastyczne wejście, które zwraca odpowiednio uformowany zestaw informacji. Dzięki temu zmniejsza się ryzyko, że klient będzie wysyłał wiele requestów, ponieważ każdy endpoint zwraca jedynie część potrzebnego kontekstu. Odpowiednio zaplanowany schemat GraphQL pozwala połączyć elastyczność z ograniczeniem liczby zapytań.
Na poziomie bazy danych ważne jest ograniczenie problemu N+1 zapytań, gdzie aplikacja dla każdego elementu listy wykonuje osobne zapytanie po powiązane dane. Mechanizmy eager loading i batch loading pozwalają pobrać relacje hurtowo. W połączeniu z cache aplikacyjnym, który przechowuje popularne odpowiedzi, znacząco zmniejsza to presję na bazę. Nawet jeśli prosty serwis radzi sobie z takim obciążeniem, w skali wzrostu ruchu szybko okazuje się ono wąskim gardłem.
Cennym narzędziem jest również throttling i debounce po stronie klienta. Interfejsy, które reagują na wpisywanie tekstu, przewijanie czy dynamiczne filtrowanie, często generują serię szybkich requestów. Zastosowanie mechanizmów opóźniających wysłanie żądania do momentu, aż użytkownik przestanie pisać, lub ograniczających częstotliwość odpytywania API, pomaga ograniczyć liczbę zapytań bez pogorszenia wrażeń z użytkowania. Wręcz przeciwnie, interfejs staje się stabilniejszy i bardziej przewidywalny.
Techniki ładowania warunkowego i code splitting
Wiele funkcji strony potrzebnych jest jedynie części użytkowników lub w określonych scenariuszach. Ładowanie wszystkiego od razu, przy pierwszym wejściu na stronę, generuje niepotrzebne requesty i wydłuża czas inicjalizacji. Rozwiązaniem jest ładowanie warunkowe (conditional loading) oraz podział kodu na logiczne fragmenty (code splitting), które są pobierane tylko wtedy, gdy są faktycznie potrzebne.
Przykładowo panel administracyjny może być ładowany dopiero w momencie, gdy zalogowany użytkownik wejdzie w odpowiednią sekcję, a nie podczas wizyty anonimowego gościa na stronie głównej. Podobnie, moduły związane z edycją treści, zaawansowanymi filtrami czy rozbudowanymi wykresami mogą być wyciągnięte do osobnych pakietów JS. Nowoczesne bundlery wspierają dynamiczne importy, które generują osobne pliki ładowane na żądanie, co pozwala utrzymać bazowy bundle niewielki.
W warstwie prezentacji dobrym przykładem są komponenty ładowane dopiero po interakcji użytkownika. Rozbudowane formularze, kreatory krok po kroku, koszyki z wieloma wariantami opcji – to wszystko może być wstrzyknięte do aplikacji dopiero w chwili kliknięcia przycisku, a nie od razu przy renderowaniu całej strony. Zmniejsza to liczbę zasobów ładowanych inicjalnie i przesuwa mniej istotne requesty na później, kiedy użytkownik realnie ich potrzebuje.
Warunkowe ładowanie dotyczy również stylów i zasobów multimedialnych. Arkusze CSS związane z rzadko używanymi motywami kolorystycznymi, trybami prezentacji czy specyficznymi widokami można podpiąć dynamicznie. Wideo w wysokiej rozdzielczości, pliki audio czy interaktywne mapy powinny być inicjowane dopiero po podjęciu konkretnej akcji, a nie przy każdym odświeżeniu strony. Takie podejście nie usuwa funkcjonalności, lecz sprawia, że jest ona dostępna w momencie, gdy ma realną wartość dla użytkownika.
Ważnym elementem jest utrzymanie równowagi między liczbą pakietów a ich rozmiarami. Nadmierne rozdrobnienie bundle’i JS czy CSS może w skrajnych przypadkach zwiększyć liczbę requestów, nawet jeśli część z nich jest mała. Dlatego code splitting powinien być świadomie planowany: kilka logicznych segmentów aplikacji zamiast dziesiątek mikrofragmentów. Ostatecznym celem jest połączenie zwinności rozwoju z kontrolą nad tym, ile i kiedy zasobów ładuje przeglądarka.
Narzędzia analityczne i proces ciągłej optymalizacji
Redukcja liczby requestów to nie jednorazowe zadanie, lecz proces. Projekty ewoluują, dochodzą nowe funkcje, biblioteki, integracje zewnętrzne. Bez konsekwentnego monitorowania łatwo stracić wypracowane optymalizacje. Kluczowe jest więc wdrożenie narzędzi analitycznych, które mierzą liczbę żądań, czas ładowania, rozmiary zasobów i wpływ poszczególnych elementów na ogólny czas reakcji serwisu.
Popularne narzędzia jak Lighthouse, PageSpeed Insights, WebPageTest czy wbudowane w przeglądarkę panele Network pozwalają szybko zobaczyć strukturę żądań. Wykres waterfall pokazuje kolejność i czas pobierania zasobów, a także umożliwia identyfikację powolnych lub zduplikowanych requestów. W połączeniu z narzędziami CI można automatyzować część analizy, na przykład blokując wdrożenia, które przekraczają określone limity liczby żądań czy rozmiaru paczek JS.
Istotnym źródłem danych są metryki RUM (Real User Monitoring), zbierane bezpośrednio z przeglądarek użytkowników. Pozwalają one zobaczyć, jak strona zachowuje się w rzeczywistych warunkach sieci, na różnych urządzeniach i w odmiennych przeglądarkach. Dzięki temu można zidentyfikować podstrony, które generują wyjątkowo dużo requestów, oraz scenariusze, w których liczba żądań rośnie gwałtownie, na przykład przy konkretnych interakcjach w SPA.
Wprowadzenie standardów kodowania i przeglądów technicznych pomaga zapobiegać powstawaniu nowych źródeł nadmiarowych zapytań. Dodanie zasobu zewnętrznego, nowej biblioteki czy integracji powinno być zawsze poprzedzone analizą wpływu na wydajność. Dokumentacja projektu może zawierać wytyczne dotyczące dopuszczalnej liczby requestów na widok, praktyk cache’owania oraz preferowanych rozwiązań, takich jak sprite’y, agregacja API czy ładowanie warunkowe.
Świadome zarządzanie zależnościami, regularne czyszczenie nieużywanego kodu i refaktoryzacja starych modułów to działania, które utrzymują liczbę requestów pod kontrolą w długim okresie. Zespół powinien mieć jasność, że optymalizacja to integralna część rozwoju produktu, a nie tylko doraźny zabieg przed kampanią marketingową. Dzięki temu każda nowa funkcja od początku projektowana jest z myślą o tym, by nie mnożyć niepotrzebnych żądań do serwera.
Podsumowanie i dobre praktyki wdrożeniowe
Zmniejszenie liczby requestów bez utraty funkcjonalności wymaga spojrzenia na aplikację jako całość: od warstwy wizualnej, przez frontend i API, aż po bazę danych i infrastrukturę sieciową. Łączenie plików CSS i JS, optymalizacja grafiki, wykorzystanie sprite’ów i fontów ikon, a także odpowiednie zarządzanie fontami to fundament warstwy prezentacji. Dobrze zaprojektowany proces build, wsparty nowoczesnymi bundlerami, pozwala zminimalizować liczbę zasobów, które musi pobrać przeglądarka przy pierwszym wejściu na stronę.
Na poziomie komunikacji z backendem kluczowe jest agregowanie zapytań API, eliminacja problemu N+1, stosowanie cache’owania dynamicznych odpowiedzi oraz przemyślane korzystanie z GraphQL lub rozbudowanych endpointów REST. Wspierająco działają mechanizmy throttlingu i debounce w interfejsie użytkownika, które ograniczają liczbę żądań generowanych przez intensywne interakcje. To połączenie pozwala zmniejszyć presję na serwer i bazę, bez rezygnowania z bogatej funkcjonalności aplikacji.
Infrastrukturalnie nieocenioną rolę odgrywają cache HTTP, CDN, odpowiednio dobrane nagłówki i kompresja danych. Pozwalają one sprawić, że wiele zasobów jest pobieranych rzadko i przechowywanych blisko użytkownika. W połączeniu z ładowaniem warunkowym, code splittingiem i lazy loadingiem obrazów otrzymujemy architekturę, w której zasoby pojawiają się wtedy, gdy są potrzebne, a nie wszystkie naraz. To najbardziej elegancki sposób na zachowanie pełnej funkcjonalności przy znacznie mniejszej liczbie realnych requestów.
Wdrożenie tych praktyk wymaga kultury technicznej: ciągłego monitorowania metryk, automatycznych testów wydajnościowych, regularnego audytu zasobów i konsekwentnego podejścia do zarządzania zależnościami. Ostatecznie redukcja liczby requestów przekłada się nie tylko na szybkość ładowania strony, ale też na lepszą skalowalność, mniejsze koszty infrastruktury i wyższą satysfakcję użytkowników. W świecie, w którym cierpliwość internautów jest ograniczona, to przewaga, której nie warto lekceważyć.
FAQ
Jak zmniejszyć liczbę requestów bez zmiany wyglądu strony?
Można połączyć pliki CSS i JS w większe pakiety, używać sprite’ów SVG lub fontów ikon zamiast wielu małych obrazków oraz włączyć cache’owanie statycznych zasobów. Dodatkowo warto korzystać z CDN i kompresji HTTP, aby rzadziej pobierać te same pliki oraz zmniejszyć ich rozmiar, nie zmieniając wyglądu ani układu interfejsu.
Czy zawsze warto maksymalnie łączyć wszystkie pliki w jeden?
Nie, zbyt duży jeden plik może spowolnić pierwszy załadunek i utrudnić cache’owanie zmian. Lepiej tworzyć kilka logicznych pakietów: podstawowy dla treści krytycznych i dodatkowe bundle ładowane warunkowo. Dzięki temu użytkownik szybko widzi najważniejszą część serwisu, a rzadziej używane funkcje nie obciążają wszystkich wizyt.
Jakie narzędzia pomagają analizować liczbę requestów?
Do analizy można użyć panelu Network w przeglądarce, Lighthouse, PageSpeed Insights oraz WebPageTest. Pokazują one liczbę, rodzaj i czas trwania poszczególnych żądań. W połączeniu z systemami RUM, które zbierają dane od realnych użytkowników, dają pełny obraz tego, gdzie powstaje nadmiar requestów i które elementy warto zoptymalizować.
Czy użycie CDN zmniejsza liczbę requestów?
CDN zwykle nie redukuje nominalnej liczby żądań, ale sprawia, że wiele z nich jest obsługiwanych z cache na brzegu sieci, bez angażowania głównego serwera. Dzięki temu rośnie wydajność i spada obciążenie backendu. CDN może też łączyć się z funkcjami kompresji i optymalizacji obrazów, co dodatkowo przyspiesza obsługę istniejących requestów.
Kiedy warto użyć GraphQL zamiast wielu endpointów REST?
GraphQL jest szczególnie przydatny, gdy frontend musi pobierać wiele powiązanych danych z różnych źródeł. Pozwala jednym zapytaniem uzyskać zestaw informacji, który w REST wymagałby kilku requestów. Jeśli jednak aplikacja jest prosta, a liczba endpointów niewielka, dobrze zaprojektowane REST API z agregacją danych może być równie efektywne i prostsze w utrzymaniu.