Beyond the primary key, an entity can declare secondary access patterns in its definition. The runtime writes the right index attributes on every record automatically — you never manage a table or a GSI.

Unique indexes

UniqueIndexes enforce cross-record uniqueness that a key alone can't. On create, the record and a uniqueness sentinel are written in one transaction; a duplicate value fails the sentinel and the whole write is cancelled.

json
"UniqueIndexes": [{ "indexName": "unique-email", "fields": ["email"] }]

Duplicate -> 409

A conflicting value returns 409 Unique constraint violation on field: <indexName>. On update, freeing a value makes it reusable; only changed indexes are touched.

Owner index

An owner index (exactly one per entity) lets GET /list/{entity} return only the calling user's records. A record created without the owner field is marked unassigned.

json
"ownerIndexes": [{
  "ownerFieldName": "user_id",
  "gpkTemplate": "org#{org};user#{user_id}",
  "gskTemplate": "task#{id}"
}]

Parent index

A parent index supports hierarchical lists — GET /list/{entity}?{parentKey}={value} returns only the children of that parent. Records without the parent field simply don't appear in the parent query.

Sorting comes for free

name, created_at, and updated_at are always indexed for sorting (?sortby=) at no extra write cost — you don't declare them.