Pagination on list endpoints
Why it matters
Unpaginated list endpoints are a denial-of-service waiting to happen: as data grows, findMany({}) with no take fetches every record in the table into memory, exhausting database connection pool, server RAM, and response bandwidth simultaneously. This maps directly to CWE-770 (allocation of resources without limits) and OWASP API 2023 API4 (unrestricted resource consumption). A single authenticated request can trigger minutes of database load. Cost-per-request grows linearly with data, making unbounded lists a latent cost bomb in addition to a reliability risk.
Severity rationale
High because even a single unbounded list query can exhaust database memory and connection pool, causing a denial-of-service condition that affects all users.
Remediation
Add offset-based or cursor-based pagination to every list endpoint in app/api/. Accept page and limit query params, enforce a maximum page size, and include pagination metadata in the response:
const page = Number(searchParams.get('page') ?? 1)
const limit = Math.min(Number(searchParams.get('limit') ?? 20), 100)
const skip = (page - 1) * limit
const [items, total] = await Promise.all([
db.post.findMany({ skip, take: limit }),
db.post.count(),
])
return apiSuccess({ items, meta: { page, limit, total } })
For high-volume tables, replace offset pagination with cursor-based pagination (pass the last record's id as a cursor) to avoid offset drift and index scans.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the API Design Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-770 — Allocation of Resources Without Limits or Throttling
- iso-25010:2011 · performance-efficiency.resource-utilization — Resource Utilization
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-api-design·automated