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.
"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.
"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.