Heimdall Scan logo, AI security scanner for vibe coders
Heimdall ScanOpen Beta
WarningPerformance

Database reads with no row limit

An unbounded query is a database read with no limit on how many rows it can return. It just pulls everything that matches the filter, however many rows that turns out to be.

#What goes wrong

A query like 'get all orders for this store' is written without a limit because during development the store has three test orders. It works, it ships, and it keeps working right up until the store has thirty thousand real orders and the same query starts timing out or exhausting server memory.

#Why it matters

An unbounded query scales with your data, not your traffic, which means your app can get slower every day even if usage stays flat, just because more rows accumulate. It's also a way for a single request to consume disproportionate memory and CPU, degrading the app for every other user at the same time.

#How Heimdall checks for this

Heimdall looks for database read queries, particularly ones over tables likely to grow, like orders, messages, logs, or events, that don't include a limit or equivalent bound.

#How to fix it

Add a limit to every list-fetching query, paired with pagination, cursor-based is usually best for growing tables, so the UI requests more data a page at a time instead of everything at once. Default to a reasonable page size, like 20 to 50 rows.

Frequently asked questions

Is a limit needed even for tables I expect to stay small?

What's the difference between offset pagination and cursor pagination?

Does adding a limit fix performance by itself?

Run this check on your own repo

Heimdall scans your GitHub repo for this and 29 other issues in under a minute.