# Why OKModel

You describe each table once, in one `schema()` call, and get typed queries and reviewed migration SQL from it. Calls that would read a whole table or change every row by accident are refused: a bare `find()` is refused until you set `limits` in `connect`, and an update or delete with no `where` is refused unless you call `.all(reason)`. Tenancy, keeping each customer's rows apart in one database, is declared on the schema too. The package has no runtime dependencies.

## What you get

| You get | Where it is shown |
| --- | --- |
| One schema for types, queries, and migrations | [How it works](/docs/concepts/how-okmodel-works), [First schema](/docs/start/first-schema) |
| Typed calls on each table (`find`, `one`, `insert`, …) | [Queries](/docs/queries) |
| Reviewed migration SQL generated from the schema, and `okm check` to report drift, a live database that no longer matches the schema | [First migration](/docs/start/first-migration), [Drift](/docs/concepts/migrations-and-drift) |
| A bare `find()` refused until you pass `limit` or `.all(reason)`, or set `limits` in `connect` | [Query limits](/docs/operate/query-limits) |
| An update or delete with no `where` refused unless you call `.all(reason)` | [First schema](/docs/start/first-schema) |
| Tenant isolation declared on the schema | [Tenant isolation](/docs/concepts/tenant-isolation) |
| No runtime dependencies; each driver is an optional peer | [Installation](/docs/start/installation) |

With no `limits` in `connect`, this read is refused before any SQL is sent:

```ts title="find-needs-limit.ts"
import { connect } from "okmodel/pg/postgresjs";
import { schema, table, t } from "okmodel/pg";

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

export async function read(url: string) {
  await using db = connect(url, { schema: app });
  // Without limits on connect, this throws OKM1101.
  await db.notes.find({ where: { id: "1" } });
}
```

```text title="find-needs-limit.err"
OkmError: find() needs a limit.
```

## What it will not do

| It will not | Why, and what you do instead |
| --- | --- |
| Support a database other than PostgreSQL | The schema and the runtime use PostgreSQL features directly, such as row-level security, `distinct on`, and transaction settings, and every release is tested on PostgreSQL 15 to 18. A dialect, the SQL one database speaks, is written only for PostgreSQL. ([Compatibility](/docs/reference/compatibility)) |
| Run on Deno | The test suites run on Node.js and Bun only, so no claim is made for Deno. Use Node.js 22.18+ or Bun 1.4+. ([Installation](/docs/start/installation)) |
| Set a default read limit by itself | Without `limits`, a `find` with no `limit` is refused. Pass `limits` to `connect` to choose the defaults. ([Query limits](/docs/operate/query-limits)) |
| Ship a driver inside the package | The package has no runtime dependencies, so installing it adds nothing besides the driver you choose. Install the peer your runtime already uses. ([Drivers](/docs/operate/drivers)) |

## Plain facts

| Fact | Detail |
| --- | --- |
| PostgreSQL | Majors 15, 16, 17, and 18 ([Minimum Postgres](/docs/schema/the-schema#minimum-postgres)) |
| Runtimes | Node.js 22.18 or newer; Bun 1.4 or newer ([CLI](/docs/reference/cli), [Drivers](/docs/operate/drivers)) |
| Drivers in the conformance table | postgres.js, node-postgres, Bun.sql, and PGlite ([Compatibility](/docs/reference/compatibility)) |
| Neon | Supported as `okmodel/pg/neon`; not a column in that table ([Drivers](/docs/operate/drivers)) |
| Deno | Unsupported ([Installation](/docs/start/installation)) |

The conformance table lists the drivers that pass the shared driver test suites: the same queries, errors, and transactions checked against each driver. `okm driver test <driver>` runs those suites ([driver test](/docs/reference/cli/check#driver-test)).

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