# Minimum Postgres

`minPostgres` is a major. [Connect](/docs/define/connect) checks the server against it. Omitted means 15, the oldest major okmodel runs. A feature below its major is refused when `schema()` runs. A bare `t.id()` stores `gen_random_uuid()` and does not need 18.

<Callout type="info" title="Not the catalog">
This field is not part of the catalog hash. Changing the floor does not change it.
</Callout>

### omitted

Omitted names 15. A bare `t.id()` stores `gen_random_uuid()`.

Connect accepts PostgreSQL 15 and newer. `okm migrate apply` still looks for an explicit `default uuidv7()` before the first statement. A server below 18 that has no `uuidv7()` function is refused, and nothing is changed. A server that already defines `uuidv7()` is accepted. A migration with no such expression does not ask the server.

```ts title="schema.ts"
import { schema, table, t } from "okmodel/pg";

const notes = table("notes", {
  id: t.id(),
  title: t.text(),
});

export default schema({
  tables: [notes],
});
```

<Callout type="error" title="OKM1803">
A server below 15, when no floor is named, is `The server is PostgreSQL 14. This schema needs PostgreSQL 15 or higher (minPostgres: 15).`
</Callout>

<Callout type="error" title="OKM1812">
A server below 18 with no `uuidv7()` function is `Column notes.id has a uuidv7() default (migration 0001_init, step 0), and the server is PostgreSQL 17. uuidv7() needs PostgreSQL 18 or higher. minPostgres: 18. Nothing was changed.` The message names the column, the migration, the step, and the server.
</Callout>

### floor

`minPostgres: 18` asks for 18 or newer. A server below that major is refused. The majors are 15, 16, 17, and 18.

```ts title="schema.ts"
import { schema, table, t } from "okmodel/pg";

const notes = table("notes", {
  id: t.id(),
  title: t.text(),
});

export default schema({
  tables: [notes],
  minPostgres: 18, // [!code focus]
});
```

### features

Each row is a feature that refuses a lower floor. The number is the major that feature needs.

| Feature | Needs |
| --- | --- |
| `uuidv7()` database default | Needs PostgreSQL 18 or higher. |

#### below 18

`minPostgres` of 15, 16, or 17 refuses a column whose default is `uuidv7()` when `schema()` runs. A bare `t.id()` is `gen_random_uuid()` and is accepted. `"uuidv4"` stores the same function. A client generator is the other way through. Both are on [id default](/docs/define/schema/defaults). An omitted floor does not refuse an explicit `uuidv7()` here. Apply checks the server.

```ts title="schema.ts"
import { schema, table, t } from "okmodel/pg";

const notes = table("notes", {
  id: t.id({ default: "uuidv4" }), // [!code focus]
  title: t.text(),
});

export default schema({
  tables: [notes],
});
```

<Callout type="error" title="OKM1812">
`uuidv7() needs PostgreSQL 18 or higher. minPostgres: 18.`
</Callout>

<Callout type="error" title="OKM1802">
A server below the floor is `The server is PostgreSQL 16. This schema needs PostgreSQL 17 or higher (minPostgres: 17).`
</Callout>

### together

A schema written for 17. Both bare `t.id()` columns already store `gen_random_uuid()`. This example sets that same function on the schema. A large write-heavy table can set `uuidv7` instead, and that choice needs Postgres 18 and `minPostgres: 18`.

```ts title="schema.ts"
import { schema, table, t } from "okmodel/pg";

const notes = table("notes", {
  id: t.id(),
  title: t.text(),
});

const sessions = table("sessions", {
  id: t.id(),
  name: t.text(),
});

export default schema({
  tables: [notes, sessions],
  minPostgres: 17, // [!code focus]
  defaults: { id: "uuidv4" },
});
```

### string

`requires: { postgres: ">=17" }` is the same floor as `minPostgres: 17`. The string form is deprecated. Passing both is an error that names both keys. `">= 17"`, `"17"`, `">=17.2"`, and a major outside 15 through 18 are errors. The error names `minPostgres` and those majors.

<Callout type="warning" title="OKM1060">
A major outside the list is `minPostgres: 15-18.` Passing both keys is `minPostgres or requires.postgres, not both.`
</Callout>
