Performance and caching
Pagination, projection and response size
Not sending the whole table: setting limits, selecting only what is needed and compressing.
Understand the concept
A list endpoint that returns ‘everything’ slows as data grows and eventually fails. Pagination returns a limited number of records per request. The simplest form is offset/limit (Skip/Take); it is easy to understand and allows jumping to a page number. On very deep pages the database must still read the skipped rows, so keyset pagination (everything after the last seen value) is preferred there.
The limit must be enforced on the server: a client can send ‘limit=100000’. In this project the blog API accepts at most 40 records per page and the interface asks for 5. Ordering must always be deterministic; unordered pagination can show the same record on two pages or skip some entirely.
Other ways to shrink responses: return only needed fields with projection, use different DTOs for list and detail views, and compress responses (Brotli/gzip). Sending a post’s full content on a list page means pushing hundreds of kilobytes the user never sees across the network.
Unbounded endpoints are both a performance and a denial-of-service risk.
Not capping the client’s limit value, or paginating without an ordering.
One topic. Three levels of depth.
var pageSize = Math.Clamp(limit, 1, 40); // sunucu tarafı üst sınır
var items = await db.Posts.AsNoTracking()
.OrderByDescending(p => p.PublishedAtUtc).ThenBy(p => p.Id) // belirli sıra
.Skip(offset).Take(pageSize)
.Select(p => new PostSummary(p.Slug, p.Title, p.Excerpt))
.ToListAsync(ct);A cap, deterministic ordering and projection together.
This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.
Try it yourself first.
/api/posts?page=500 takes 4 seconds while page=1 takes 20 ms. Why, and what do you suggest?
Show the solution and explanation
OFFSET büyüdükçe veritabanı atlanan bütün satırları okur (500 × sayfa boyutu).
Öneri: keyset sayfalama (son görülen tarih+id’den sonrası)
veya derin sayfalara erişimi sınırlamak; uygun indeks (PublishedAtUtc, Id).Offset pagination cost grows linearly with page number; keyset stays constant.