Root Field Visibility
Introduction
Sometimes you may want a role to only have access to certain root fields of a table or have the table only be accessible through a relationship.
When you track a table in Hasura Engine, all the GraphQL root fields available to the role are exposed. Ie: Under
the query root field: select, select_by_pk and select_aggregate are exposed. Under the subscription
root field, select, select_by_pk, select_aggregate and select_stream are exposed. Root field visibility can
disable specific query and subscription root fields.
Root field visibility is supported in version v2.8.0 and above.
- Console
- CLI
- API
You can disable specific root fields for queries and subscriptions by unchecking them in the Select permission for the table and role in Console. This is located in the Console under Data -> {table} -> Permissions -> {role} -> select -> Root fields permissions

You can disable root fields for queries and subscriptions specifying which are available for the select_permissions by
updating the specific metadata -> databases -> [database-name] -> tables -> [table-name].yaml file eg:
table:
name: users
schema: public
select_permissions:
- role: user
permission:
columns:
- id
filter: {}
query_root_fields:
- select_by_pk
subscription_root_fields:
- select
- select_by_pk
- select_aggregate
delete_permissions:
- role: user
permission:
backend_only: true
filter: {}
Setting the value of query_root_fields or subscription_root_fields to null or not defining it at all implies that
all fields are allowed and an empty array means no fields are allowed.
You can disable root fields for Select permissions with the
permissions Metadata API by specifying which should be available in
the query_root_fields and subscription_root_fields arrays, eg:
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin
{
"type" : "pg_create_select_permission",
"args" : {
"table" : "users",
"role" : "user",
"source": "default",
"permission" : {
"columns" : "*",
"filter" : {
"is_public": true
},
"query_root_fields": ["select_by_pk"],
"subscription_root_fields": ["select", "select_by_pk"]
}
}
}
Setting the value of query_root_fields or subscription_root_fields to null or not defining it at all implies that
all fields are allowed and an empty array means no fields are allowed.
Root field visibility use cases
Allow a table to be accessible only through a relationship
Let's say we have two tables, categories and products defined as follows:
| Table | Columns | Relationships |
|---|---|---|
| categories | id, name | products (array relationship) |
| products | id, name, description, price | category (object relationship) |
We would like to configure permissions of the guest role such that they are only able to access the products of the
categories which they can access i.e. access the products table only through the categories -> products
relationship.
Modifying the select permission of the products table:

Now that no query_root_fields or subscription_root_fields are enabled, the guest role won't be able to access
the products table directly and can only access the products table through the categories -> products
relationship.

If root fields are disabled then you may want to simplify the row filter permissions by giving it "without any checks"
access to all rows. But you should be cautious here because the field may be accessible through a different type e.g.
the returning field in a mutation output type.
Access only via primary key
Let's say you want to allow a client to fetch data from a table only if the client knows the primary key of a row in that table.
In this case, regardless of the permission on the table, only <table>_by_pk should be exposed in query_root.

Disable subscription fields
Allow a role to only be able to make query and not subscription requests.
