# Limits

By default a read with no `limit` is refused (OKM1101 for `find`, `page`, and a grouped aggregate; OKM1105 for a to-many `include`). `limits` is an opt-in default for those calls. Leave it out and nothing changes.

```ts
import { connect } from "okmodel/pg/postgresjs";
import { schema, table, t } from "okmodel/pg";
import { warnings } from "okmodel/warnings";

const notesTable = table("notes", { id: t.identity(), title: t.text() });
const app = schema({ tables: [notesTable] });

export const db = connect(process.env.DATABASE_URL ?? "", {
  schema: app,
  limits: { find: 50, include: 20, page: 25, groupBy: 100, max: 1000 },
  warnings: warnings(),
});
```

Every key is optional and independent. `include` and `groupBy` never take the value of `find`. A key you leave out keeps today's rule for that call.

| Key | Applies to |
| --- | --- |
| `find` | `find` with no `limit` and no `.all(reason)`. That includes `search`, `matches`, presets, and relation filters. |
| `include` | A to-many `include` (`many` and `manyThrough`, at any depth) with no `limit`. A to-one include has no limit. |
| `page` | The page size of `page()` with no `limit`. |
| `groupBy` | `aggregate` with `groupBy` and no `limit`. |
| `max` | A ceiling for the `limit` you write, on `find`, `page()`, `aggregate`, and `include`. |

```ts
const notes = await db.notes.find({ orderBy: { id: "asc" } }); // limit 50
const few = await db.notes.find({ orderBy: { id: "asc" }, limit: 5 }); // limit 5
const every = await db.notes.find({ orderBy: { id: "asc" } }).all("nightly export"); // no limit
```

A call that states a `limit` or `.all(reason)` never takes a default.

## max

`max` is a hard ceiling. A `limit` above it is OKM1101, and the fix is `.all(reason)`, which reads past `max` on purpose.

```ts
await db.notes.find({ orderBy: { id: "asc" }, limit: 5000 }); // OKM1101
await db.notes.find({ orderBy: { id: "asc" }, limit: 5000 }).all("backfill"); // allowed
```

## What limits do not touch

`.stream()`, `one`, `count`, `exists`, an `aggregate` without `groupBy`, the `limit` of `update` and `delete`, bulk write predicates, and `raw()`.

## Check at connect

`limits` is checked once, when the client connects. Each key is a positive integer, the keys are `find`, `include`, `page`, `groupBy`, and `max`, and no key is above `max`. A bad value is OKM1120 and rejects `connected` (and the first query).

## See the limit

`.inspect()` lists the `bounded` rule with the source: `limits.find`, `limits.page`, `limits.groupBy`, or `limits.include` (provenance `connect`). A `limit` you wrote shows as `limit` (provenance `caller`). The `onQuery` event carries `limit: { value, source }` for the root read.

## OKM2011

A default can hide rows. With `warnings` on, a read that took a default and returned exactly that many rows is OKM2011 in development: the call site, the key (`limits.find = 50`), and the fix. The fix is a `limit` that fits the call, `page()`, or `.all(reason)`.

The warning never fires for a limit you wrote, for `.all(reason)`, or for `page()`. In production every warning is off until `levels` turns it on. See [Warnings](/docs/reference/warnings).

Index: [/llms.txt](/llms.txt)
