This feature is in beta and subject to change.
Declarative custom data definitions
The Next-Gen Dev Platform is not yet generally available. Currently, access to these tools and features is limited to organizations participating in an invitation-only early access program. To request entry into the early access program, submit a request.
Visit our dev community to discuss the Next-Gen Dev Platform and provide feedback.
Declarative custom data definitions make it easier to manage your metafields and metaobjects. Managing definitions via API is challenging for statically defined schemas:
-
Definitions are created during the application's runtime. That necessitates post-install hooks to check for and update existing definitions, with no rollback option in case of errors.
-
Schema migrations may require custom scripts to update each store individually.
-
Limits are scoped to the shop and shared among apps.
Declarative custom data definitions address these considerations:
-
Metafield and metaobject definitions are organized in TOML and managed through the new Shopify app development command.
-
Shopify automatically distributes definitions to multiple shops in parallel, accelerating migrations.
-
Updates are atomic, ensuring all stores maintain the same version of your definitions.
-
All declarative definitions come with app-scoped limits, eliminating competition for resources among apps.
If your use case requires dynamically creating definitions, we still recommend using the API. For all other scenarios, we recommend declarative custom data definitions.
Anchor to ExampleExample
In this scenario, you want to display custom payment messages in Checkout based on the selected payment method. This can be achieved by defining a metaobject for payment messages and associating it with payment types.
Anchor to Creating the metaobject definitionCreating the metaobject definition
First, declare the payment messages metaobject definition in your shopify.app.toml
file:
Anchor to Creating a metaobject entryCreating a metaobject entry
To create a payment message metaobject entry, use the GraphQL Admin API mutation metaobjectCreate
:
Anchor to Retrieve your metaobject entryRetrieve your metaobject entry
You can retrieve your payment message metaobject entries using the metaobjects
query:
Anchor to Adding validations to the metaobject definitionAdding validations to the metaobject definition
To restrict the allowed values for payment_type
, add a validations.choices
property to the field in your shopify.app.toml
:
Try to create a metaobject entry with an invalid payment_type
value:
The response will include a userErrors
entry indicating that the value for payment_type
is not allowed.
Now, create a metaobject entry with a valid payment_type
value:
This mutation will succeed and return the created metaobject entry, with an empty userErrors
array.
Anchor to Modifying access controlsModifying access controls
You can control who can read or write to your metaobject definitions by adding access states to your TOML configuration. For example, to allow merchant read/write access in the admin, update your definition as follows:
After deploying your changes, you can see the updated access controls reflected in the Shopify Admin. Navigate to the Metaobjects tab within Content; you should see the payment_messages
definition visible. This means the merchant can now modify entries on the definition.

Anchor to ReferenceReference
shopify.app.toml
Anchor to Metafield configurationMetafield configuration
Metafields are declared using the format [<owner_type>.metafields.app.<key>]
. For example, [product.metafields.app.page_count]
declares a Product metafield, with namespace $app
and key page_count
.
Metafields can be defined on many different resource types (e.g. product
). For a full list, see MetafieldOwnerType.
Property | Description |
---|---|
type | Data type for the metafield. See metafield data types for all available options. |
name | Human-readable name displayed in the Shopify admin. |
description | Descriptive text that explains the purpose of the metafield. |
access.admin | Admin API access control: merchant_read or merchant_read_write . |
access.storefront | Storefront access control: public_read , private_read , or none . |
access.customer_account | Customer API access control: public_read , public_read_write , private_read , private_read_write , or none . |
capabilities.admin_filterable | When true , enables filtering by this metafield in the admin UI & admin API. |
validations | Rules to validate field values (e.g., min/max values, regex patterns). See validation rules. |
Anchor to Metaobject configurationMetaobject configuration
Metaobjects are declared using the format [metaobjects.app.<metaobject_name />]
. For example, [metaobjects.app.author]
declares a metaobject named author
, with type name $app:author
.
Property | Description |
---|---|
name | Human-readable name displayed in the Shopify admin. |
description | Descriptive text that explains the purpose of the metaobject. |
display_name_field | Key of a field to reference as the display name for each object. |
access.admin | Admin API access control: merchant_read or merchant_read_write . |
access.storefront | Storefront access control: public_read , private_read , or none . |
capabilities.publishable | When true , enables draft/active status for content workflow. See metaobject capabilities. |
capabilities.translatable | When true , enables translation support for fields. See translatable content. |
capabilities.renderable | When true , enables metaobject SEO fields on Liquid and the Storefront API. See metaobjects as web pages. |
Anchor to Metaobject fields configurationMetaobject fields configuration
Metaobject fields are declared using the format [metaobjects.app.<metaobject_name />.fields.<field_name>]
. For example, [metaobjects.app.author.fields.birthday]
declares a field named birthday
on the author
metafield.
Property | Description |
---|---|
type | Data type for the field. Uses the same types as metafields. See metafield data types. |
name | Human-readable name displayed in the Shopify admin. |
description | Descriptive text that explains the purpose of the field. |
required | When true , the field must have a value when saving the metaobject. |
validations | Rules to validate field values based on the field type. See validation rules. |
Anchor to LimitationsLimitations
Anchor to App-reserved namespaceApp-reserved namespace
You can only declare metafield and metaobject definitions in the app-reserved namespace ($app
) to ensure that only the owning app can make changes to definitions. This constraint allows Shopify to guarantee a consistent state between all shops your app is installed on.
Anchor to App-scoped metafield and metaobject limitsApp-scoped metafield and metaobject limits
There are limits on the total number of definitions within an app.
-
Metafield definitions per owner type:
128
-
Metaobject definitions:
32
-
Field definitions per metaobject:
64
To ensure Shopify can quickly and reliably distribute definitions across shops, you can't make more than 25 metafield and metaobject changes (creation, update or deletion) in a single deploy. If you need to make more than 25 changes, you will need to do so over multiple deploys.
Anchor to Admin APIAdmin API
Declarative definitions are read-only through the Admin API, and can only be updated or deleted through the TOML configuration file. You can query declarative definitions through the Admin API, but mutations will return an error.
Anchor to Capability supportCapability support
Support for currently unsupported capabilities is coming later in 2025.
Anchor to MetafieldsMetafields
Capability | Supported? |
---|---|
Smart collections | ❌ |
Admin filterable | ✅ |
Unique values | ❌ |
Pinning | ❌ |
Anchor to MetaobjectMetaobject
Capability | Supported? |
---|---|
Publishable | ✅ |
Translatable | ✅ |
Renderable | ✅ |
Online Store | ❌ |
Anchor to Making GraphQL calls with AI IDEsMaking Graph QL calls with AI IDEs
When the user is running the dev server, they will also be running a GQL proxy server on http://localhost:3457/graphiql/graphql.json?key=&api_version=2025-07 where you can POST graphql queries and they will be run against their dev store.