𝗠𝘆 𝗔𝗣𝗜 𝗥𝗲𝘀𝗽𝗼𝗻𝗱𝗲𝗱 𝗶𝗻 𝟰 𝗺𝘀, 𝗯𝘂𝘁 𝗡𝗮𝘃𝗶𝗴𝗮𝘁𝗶𝗼𝗻 𝗦𝘁𝗶𝗹𝗹 𝗙𝗲𝗹𝘁 𝗦𝗹𝗼𝘄
I was debugging a project management app built with SvelteKit and a Rust API.
On my local machine, everything felt instant. On the VPS, navigation felt heavy. Opening pages like Tickets or Timeline took too long. Clicking a ticket caused a noticeable delay before the preview appeared.
I thought the problem was the server. I suspected slow database queries or a weak VPS.
The measurements proved me wrong.
I checked the feature list endpoint. For only 52 tickets, the API responded in 4 ms. That sounds fast. But the response size was 354 KB.
The SvelteKit route payload showed the same issue. The data size was huge for a simple list.
The problem was not speed. The problem was weight.
The descriptions alone made up 80% of the total response. The list endpoint was returning full Markdown descriptions for every single item.
This is a common trap. The list endpoint had become a detail endpoint. Every time a page needed a list, it paid the price for data it did not use.
The UI usage does not determine the payload. The loader return shape does.
If your loader returns a full object, SvelteKit serializes that entire object into the route data. Even if you never render a field, it still travels across the network.
I fixed this by separating summary data from detail data.
I created two different contracts:
• A list contract for summaries (ID, title, status, dates). • A detail contract for full information (descriptions, commands).
I split the API into two endpoints:
- GET /features (returns summaries)
- GET /features/:id (returns one full detail)
I also changed how the frontend works. Now, the app renders the list immediately using summary data. When you click a ticket, the app shows a shell and fetches the heavy detail data in the background.
The results were massive:
• Feature list API: 89.6% reduction • Tickets route data: 91.4% reduction • OpenSpec docs API: 98.9% reduction
The database was always fast. The real bottleneck was the data contract between the API and the page.
Lessons for list-heavy apps:
- Messen Sie die Antwortgröße, nicht nur die Antwortzeit.
- Behandeln Sie List- und Detail-Payloads als separate Einheiten.
- Geben Sie in einer Listenansicht niemals große Textfelder zurück.
- Überprüfen Sie, was Ihr SSR-Loader tatsächlich serialisiert.
- Laden Sie Detaildaten per Lazy-Loading, aber zeigen Sie die UI-Shell sofort an.
- Verwenden Sie keinen Lade-Spinner, um eine schwere Payload zu kaschieren.
Eine schnelle Abfrage garantiert keine schnelle Seite.
Quelle: https://dev.to/ahikmah/my-api-responded-in-4-ms-but-navigation-still-felt-slow-1hk8