ponder.schema.ts – Ponder
Skip to content

ponder.schema.ts

API reference

The ponder.schema.ts file defines your database tables and their relationships. Each table you include in ponder.schema.ts will be created as an SQL table, populated during indexing, and exposed via the GraphQL API.

File requirements

The ponder.schema.ts must use named exports for tables, enums, and relations. These objects must be created using the correct functions exported from "ponder".

ponder.schema.ts
import { onchainTable } from "ponder";
 
export const pets = onchainTable("pets", (t) => ({
  name: t.text().primaryKey(),
  age: t.integer().notNull(),
}));

onchainTable

The onchainTable function accepts three positional arguments.

fieldtypedescription
namestringThe SQL table name. Use snake_case.
columns(t: TableBuilder) => Record<string, Column>A function that returns column definitions.
constraints(table: Table) => Record<string, Constraint>Optional function that returns table constraints like composite primary keys and indexes.
ponder.schema.ts
import { onchainTable } from "ponder";
 
export const transferEvents = onchainTable(
  "transfer_event", // SQL table name
  (t) => ({ // Column definitions
    id: t.text().primaryKey(),
    from: t.hex().notNull(),
    to: t.hex().notNull(),
    value: t.bigint().notNull(),
  }),
  (table) => ({ // Constraints & indexes
    fromIdx: index().on(table.from),
  })
);

Column types

The schema definition API supports most PostgreSQL data types. Here's a quick reference for the most commonly used data types. For a complete list, visit the Drizzle documentation.

namedescriptionTypeScript typeSQL data type
textUTF‐8 character sequencestringTEXT
integerSigned 4‐byte integernumberINTEGER
realSigned 4-byte floating‐point valuenumberREAL
booleantrue or falsebooleanBOOLEAN
timestampDate and time value (no time zone)DateTIMESTAMP
jsonJSON objectany or customJSON
bigintLarge integer (holds uint256 and int256)bigintNUMERIC(78,0)
hexUTF‐8 character sequence with 0x prefix0x${string}TEXT

Column modifiers

Column modifiers can be chained after column type definitions.

modifierdescription
.primaryKey()Marks column as the table's primary key
.notNull()Marks column as NOT NULL
.array()Marks column as an array type
.default(value)Sets a default value for column
.$default(() => value)Sets a dynamic default via function
.$type<T>()Annotates column with a custom TypeScript type

Constraints

Primary key

Every table must have exactly one primary key defined using either the .primaryKey() column modifier or the primaryKey() function in the table constraints argument.

ponder.schema.ts
import { onchainTable, primaryKey } from "ponder";
 
// Single column primary key
export const tokens = onchainTable("tokens", (t) => ({
  id: t.bigint().primaryKey(),
}));
 
// Composite primary key
export const poolStates = onchainTable(
  "pool_states",
  (t) => ({
    poolId: t.bigint().notNull(),
    address: t.hex().notNull(),
  }),
  (table) => ({
    pk: primaryKey({ columns: [table.poolId, table.address] }),
  })
);

Indexes

Create indexes using the index() function in the constraints & indexes argument. Ponder creates database indexes after historical indexing completes, just before the app becomes ready.

ponder.schema.ts
import { onchainTable, index } from "ponder";
 
export const persons = onchainTable(
  "persons",
  (t) => ({
    id: t.text().primaryKey(),
    name: t.text(),
  }),
  (table) => ({
    nameIdx: index().on(table.name),
  })
);

onchainEnum

The onchainEnum function accepts two positional arguments. It returns a function that can be used as a column type.

fieldtypedescription
namestringThe SQL enum name. Use snake_case.
valuesstring[]An array of strings representing the allowed values for the enum.
ponder.schema.ts
import { onchainEnum, onchainTable } from "ponder";
 
export const color = onchainEnum("color", ["ORANGE", "BLACK"]);
 
export const cats = onchainTable("cats", (t) => ({
  name: t.text().primaryKey(),
  color: color().notNull(),
}));

Like any other column types, you can use modifiers like .notNull(), .default(), and .array() with enum columns.

ponder.schema.ts
// ...
 
export const dogs = onchainTable("cats", (t) => ({
  name: t.text().primaryKey(),
  color: color().array().default([]),
}));

relations

Use the relations function to define relationships between tables.

ponder.schema.ts
import { onchainTable, relations } from "ponder";
 
export const users = onchainTable("users", (t) => ({
  id: t.text().primaryKey(),
}));
 
export const usersRelations = relations(users, ({ one }) => ({
  profile: one(profiles, {
    fields: [users.id],
    references: [profiles.userId],
  }),
}));

Relationship types

typemethoddescription
One-to-oneone()References single related record
One-to-manymany()References array of related records
Many-to-manyCombinationUses join table with two one-to-many relations

Read more in the relationships guide and the Drizzle relations documentation.