# Id default

`defaults` has one field, `id`. It replaces a bare `t.id()`. A column that passes `default` is left alone. `"none"` is that column option. It is not a schema value.

The id is omitted from insert for a database default and for a client generator. `"none"` is required on insert and still omitted from update.

### omitted

Omitted and `{}` store `gen_random_uuid()`. `"uuidv4"` stores the same function. It is built in from Postgres 13, so a bare `t.id()` works on every supported major. Random ids are fine for most tables. A large write-heavy table can pick `uuidv7`: the ids are time-ordered and the index stays local. That function needs Postgres 18.

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

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

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

### uuidv7

`"uuidv7"` stores `uuidv7()`. Keep the previous default with `defaults: { id: "uuidv7" }`.

```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],
  defaults: { id: "uuidv7" }, // [!code focus]
});
```

<Callout type="error" title="OKM1812">
`uuidv7()` needs PostgreSQL 18 or higher. A [minPostgres](/docs/define/schema/min-postgres) floor below 18 is `uuidv7() needs PostgreSQL 18 or higher. minPostgres: 18.` An omitted floor does not name a version, so an explicit `uuidv7()` stays until apply.
</Callout>

### uuidv4

`"uuidv4"` stores `gen_random_uuid()`, the same expression a bare `t.id()` stores. That function is built in from Postgres 13.

```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],
  defaults: { id: "uuidv4" }, // [!code focus]
});
```

### client

A generator from `okmodel/ids` runs on insert. The catalog stores no default. Changing an OKID prefix, length, or sortable flag does not change the catalog hash. The SQL type does: `okid()` is `text`, and `uuidv4` or `uuidv7` stay `uuid`.

#### uuid

`uuidv4` and `uuidv7` stay `uuid`. The client `uuidv7` mints a time-ordered id, so a server older than Postgres 18 can still use one.

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

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

export default schema({
  tables: [sessions],
  defaults: { id: uuidv7 }, // [!code focus]
});
```

#### okid

`okid()` is `text` with collation `C`. Calling it returns the generator. It does not mint the id here. Length, prefix, and sortable are on [OKID](/docs/define/table/columns#okid).

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

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

export default schema({
  tables: [users],
  defaults: { id: okid({ prefix: "usr_" }) }, // [!code focus]
});
```

### column

A column option wins. A bare `t.id()` takes the schema default. `t.id({ default: "uuidv4" })` stays `gen_random_uuid()` and stays `uuid`.

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

const users = table("users", {
  id: t.id(), // [!code focus]
  name: t.text(),
});

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

export default schema({
  tables: [users, sessions],
  defaults: { id: okid({ prefix: "usr_" }) },
});
```

<Callout type="warning" title="OKM1060">
Anything other than an object is `schema() defaults must be an object.` Another key is `schema() defaults.createdAt is not a schema default. Accepted names: id.` Another value, including `"none"`, is `schema() defaults.id must be "uuidv7", "uuidv4", or a client generator.`
</Callout>
