Limits

Opt-in default limits for find, to-many include, page, and groupBy, with a hard ceiling.

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.

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.

KeyApplies to
findfind with no limit and no .all(reason). That includes search, matches, presets, and relation filters.
includeA to-many include (many and manyThrough, at any depth) with no limit. A to-one include has no limit.
pageThe page size of page() with no limit.
groupByaggregate with groupBy and no limit.
maxA ceiling for the limit you write, on find, page(), aggregate, and include.
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.

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.