## Customize primary keys By default, DataStore models have an `id` field that is automatically populated on the client with a UUID v4, allowing DataStore to generate non-colliding globally unique identifiers in a scalable way. While UUIDs have desirable properties (they are large, non-sequential and opaque), there are times when a custom primary key, also known as custom identifier, is needed. For instance, to: - Have friendly/readable identifiers (surrogate/opaque vs. natural keys) - Define composite primary keys - Customize data partitioning to optimize for scale (especially important when planning to handle large amounts of data in short periods of time) - Selectively synchronize data to clients (e.g. by fields like `deviceId`, `userId` or similar) - Prioritize the sort order in which objects are returned by the sync queries - Make existing data consumable and syncable by DataStore A schema with the typical `id` field looks like this: ```graphql type Book @model { id: ID! title: String! description: String } ``` You can customize the primary key by adding the `@primaryKey` directive to a field: ```graphql type Book @model { isbn: ID! @primaryKey title: String! description: String } ``` You can also require multiple fields to define your primary key. When your primary key references multiple fields, it's called a **composite key**. In the example below, the primary key is defined by the `isbn` and `title` fields: ```graphql type Book @model { isbn: ID! @primaryKey(sortKeyFields: ["title"]) title: String! description: String } ``` ### Determine when the primary key field is auto-populated upon record creation When you create a record with DataStore, a UUID is automatically populated for the default `id: ID!` primary key field. When working with custom primary keys, DataStore will automatically populate the key fields in the following conditions:
Description | Type | Autopopulated with UUID |
---|---|---|
Without `@primaryKey` | ```graphql type Customer @model { firstName: String lastName: String } ``` | ✅ Yes |
Without `@primaryKey`, explicit `id` field | ```graphql type Customer @model { id: ID! firstName: String lastName: String } ``` | ✅ Yes |
`@primaryKey` on a custom field | ```graphql type Customer @model { customerId: ID! @primaryKey firstName: String lastName: String } ``` | ❌ No |
Explicit `@primaryKey` on `id` field | ```graphql type Customer@model { id: ID! @primaryKey dob: AWSDateTime! firstName: String lastName: String } ``` | ✅ Yes |
Explicit `@primaryKey` on `id` field with sort key | ```graphql type Customer @model { id: ID! @primaryKey (sortKeyFields: ["dob"]) dob: AWSDateTime! firstName: String lastName: String } ``` | ✅ Yes |
Explicit `id` field in sort key | ```graphql type Customer@model { country: String! @primaryKey (sortKeyFields: ["id"]) id: ID! firstName: String lastName: String } ``` | ✅ Yes |
@primaryKey with no `id` field | ```graphql type Customer @model { zip: String! @primaryKey (sortKeyFields: ["username"]) username: String! firstName: String lastName: String } ``` | ❌ No |