Directives Stay organized with collections Save and categorize content based on your preferences.
This reference doc is generated based on thisexample schema.
Directives define specific behaviors that can be applied to fields or types within Data Connect schema and connectors.
Data Connect defines GraphQL directives to map schema to SQL tables and customize behavior of queries and mutations.
Data Connect Defined
@auth onQUERY |MUTATION
The@auth directive defines the authentication policy for a query or mutation.
It must be added to any operation that you wish to be accessible from a clientapplication. If not specified, the operation defaults to@auth(level: NO_ACCESS).
Refer toData Connect Auth Guide for the best practices.
| Argument | Type | Description |
|---|---|---|
level | AccessLevel | The minimal level of access required to perform this operation. Exactly one oflevel andexpr should be specified. |
expr | Boolean_Expr | A CEL expression that grants access to this operation if the expression evaluates totrue. Exactly one oflevel andexpr should be specified. |
insecureReason | String | If the@auth on this operation is considered insecure, then developer acknowledgement is required to deploy this operation, for new operations.@auth is considered insecure iflevel: PUBLIC, or iflevel: USER/USER_ANON/USER_EMAIL_VERIFIED andauth.uid is not referenced in the operation. IfinsecureReason is set, no further developer acknowledgement is needed. |
@check onQUERY |MUTATION |FIELD |FRAGMENT_DEFINITION |FRAGMENT_SPREAD |INLINE_FRAGMENT
Ensure this field is present and is not null or[], or abort the request / transaction.
A CEL expression,expr is used to test the field value. It defaults torejecting null and[] but a custom expression can be provided instead.
If the field occurs multiple times (i.e. directly or indirectly nested under alist),expr will be executed once for each occurrence and@check succeeds ifall values succeed.@check fails when the field is not present at all (i.e.all ancestor paths containnull or[]), unlessoptional is true.
If a@check fails in a mutation, the top-level field containing it will bereplaced with a partial error, whose message can be customzied via themessageargument. Each subsequent top-level fields will return an aborted error (i.e.not executed). To rollback previous steps, see@transaction.
| Argument | Type | Description |
|---|---|---|
expr | Boolean_Expr! | The CEL expression to test the field value (or values if nested under a list). Within the CEL expression, a special valuethis evaluates to the field that this directive is attached to. If this field occurs multiple times because any ancestor is a list, each occurrence is tested withthis bound to each value. When the field itself is a list or object,this follows the same structure (including all descendants selected in case of objects). For any given path, if an ancestor isnull or[], the field will not be reached and the CEL evaluation will be skipped for that path. In other words, evaluation only takes place whenthis isnull or non-null, but never undefined. (See also theoptional argument.) |
message | String! | The error message to return to the client if the check fails. Defaults to "permission denied" if not specified. |
optional | Boolean | Whether the check should pass or fail (default) when the field is not present. A field will not be reached at a given path if its parent or any ancestor is[] ornull. When this happens to all paths, the field will not be present anywhere in the response tree. In other words,expr is evaluated 0 times. By default, @check will automatically fail in this case. Set this argument totrue to make it pass even if no tests are run (a.k.a. "vacuously true"). |
@col onFIELD_DEFINITION
Customizes a field that represents a SQL database table column.
Data Connect maps scalar Fields on@table type to a SQL column ofcorresponding data type.
- scalar
UUIDmaps touuid. - scalar
Stringmaps totext. - scalar
Intmaps toint. - scalar
Int64maps tobigint. - scalar
Floatmaps todouble precision. - scalar
Booleanmaps toboolean. - scalar
Datemaps todate. - scalar
Timestampmaps totimestamptz. - scalar
Anymaps tojsonb. - scalar
Vectormaps topgvector.
Array scalar fields are mapped toPostgres arrays.
Example: Serial Primary Key
For example, you can define auto-increment primary key.
typePost@table{id:Int!@col(name:"post_id",dataType:"serial")}Data Connect converts it to the following SQL table schema.
CREATETABLE"public"."post"("post_id"serialNOTNULL,PRIMARYKEY("id"))Example: Vector
typePost@table{content:String!@col(name:"post_content")contentEmbedding:Vector!@col(size:768)}| Argument | Type | Description |
|---|---|---|
name | String | The SQL database column name. Defaults to snake_case of the field name. |
dataType | String | Configures the custom SQL data type. Each GraphQL type can map to multiple SQL data types. Refer toPostgres supported data types. Incompatible SQL data type will lead to undefined behavior. |
size | Int | Required onVector columns. It specifies the length of the Vector.textembedding-gecko@003 model generatesVector of@col(size:768). |
@default onFIELD_DEFINITION
Specifies the default value for a column field.
For example:
typeUser@table(key:"uid"){uid:String!@default(expr:"auth.uid")number:Int!@col(dataType:"serial")createdAt:Date!@default(expr:"request.time")role:String!@default(value:"Member")credit:Int!@default(value:100)}The supported arguments vary based on the field type.
| Argument | Type | Description |
|---|---|---|
value | Any | A constant value validated against the field's GraphQL type during compilation. |
expr | Any_Expr | A CEL expression whose return value must match the field's data type. |
sql | Any_SQL | A raw SQL expression, whose SQL data type must match the underlying column. The value is any variable-free expression (in particular, cross-references to other columns in the current table are not allowed). Subqueries are not allowed either. SeePostgreSQL defaults for more details. |
@index onFIELD_DEFINITION |OBJECT
Defines a database index to optimize query performance.
typeUser@table@index(fields:["name","phoneNumber"],order:[ASC,DESC]){name:String@indexphoneNumber:Int64@indextags:[String]@index# GIN Index}Single Field Index
You can put@index on a@col field to create a SQL index.
@index(order) matters little for single field indexes, as they can be scannedin both directions.
Composite Index
You can put@index(fields: [...]) on@table type to define composite indexes.
@index(order: [...]) can customize the index order to satisfy particularfilter and order requirement.
| Argument | Type | Description |
|---|---|---|
name | String | Configure the SQL database index id. If not overridden, Data Connect generates the index name: -{table_name}_{first_field}_{second_field}_aa_idx -{table_name}_{field_name}_idx |
fields | [String!] | Only allowed and required when used on a@table type. Specifies the fields to create the index on. |
order | [IndexFieldOrder!] | Only allowed forBTREE@index on@table type. Specifies the order for each indexed column. Defaults to allASC. |
type | IndexType | Customize the index type. For most index, it defaults toBTREE. For array fields, only allowedIndexType isGIN. ForVector fields, defaults toHNSW, may configure toIVFFLAT. |
vector_method | VectorSimilarityMethod | Only allowed when used on vector field. Defines the vector similarity method. Defaults toINNER_PRODUCT. |
@redact onFIELD |FRAGMENT_SPREAD |INLINE_FRAGMENT
Redact a part of the response from the client.
Redacted fields are still evaluated for side effects (including data changes and@check) and the results are still available to later steps in CEL expressions(viaresponse.fieldName).
@ref onFIELD_DEFINITION
Defines a foreign key reference to another table.
For example, we can define a many-to-one relation.
typeManyTable@table{refField:OneTable!}typeOneTable@table{someField:String!}Data Connect adds implicit foreign key column and relation query field. So theabove schema is equivalent to the following schema.
typeManyTable@table{id:UUID!@default(expr:"uuidV4()")refField:OneTable!@ref(fields:"refFieldId",references:"id")refFieldId:UUID!}typeOneTable@table{id:UUID!@default(expr:"uuidV4()")someField:UUID!# Generated Fields:# manyTables_on_refField: [ManyTable!]!}Data Connect generates the necessary foreign key constraint.
CREATETABLE"public"."many_table"("id"uuidNOTNULLDEFAULTuuid_generate_v4(),"ref_field_id"uuidNOTNULL,PRIMARYKEY("id"),CONSTRAINT"many_table_ref_field_id_fkey"FOREIGNKEY("ref_field_id")REFERENCES"public"."one_table"("id")ONDELETECASCADE)Example: Traverse the Reference Field
query($id:UUID!){manyTable(id:$id){refField{id}}}Example: Reverse Traverse the Reference field
query($id:UUID!){oneTable(id:$id){manyTables_on_refField{id}}}Optional Many-to-One Relation
An optional foreign key reference will be set to null if the referenced row is deleted.
In this example, if aUser is deleted, theassignee andreporterreferences will be set to null.
typeBug@table{title:String!assignee:Userreproter:User}typeUser@table{name:String!}Required Many-to-One Relation
A required foreign key reference will cascade delete if the referenced row isdeleted.
In this example, if aPost is deleted, associated comments will also bedeleted.
typeComment@table{post:Post!content:String!}typePost@table{title:String!}Many To Many Relation
You can define a many-to-many relation with a join table.
typeMembership@table(key:["group","user"]){group:Group!user:User!role:String!@default(value:"member")}typeGroup@table{name:String!}typeUser@table{name:String!}When Data Connect sees a table with two reference field as its primary key, itknows this is a join table, so expands the many-to-many query field.
typeGroup@table{name:String!# Generated Fields:# users_via_Membership: [User!]!# memberships_on_group: [Membership!]!}typeUser@table{name:String!# Generated Fields:# groups_via_Membership: [Group!]!# memberships_on_user: [Membership!]!}Example: Traverse the Many-To-Many Relation
query($id:UUID!){group(id:$id){users:users_via_Membership{name}}}Example: Traverse to the Join Table
query($id:UUID!){group(id:$id){memberships:memberships_on_group{user{name}role}}}One To One Relation
You can even define a one-to-one relation with the help of@unique or@table(key).
typeUser@table{name:String}typeAccount@table{user:User!@unique}# Alternatively, use primary key constraint.# type Account @table(key: "user") {# user: User!# }Example: Transerse the Reference Field
query($id:UUID!){account(id:$id){user{id}}}Example: Reverse Traverse the Reference field
query($id:UUID!){user(id:$id){account_on_user{id}}}Customizations
@ref(constraintName)can customize the SQL foreign key constraint name (table_name_ref_field_fkeyabove).@ref(fields)can customize the foreign key field names.@ref(references)can customize the constraint to reference other columns.By default,@ref(references)is the primary key of the@reftable.Other fields with@uniquemay also be referred in the foreign key constraint.
| Argument | Type | Description |
|---|---|---|
constraintName | String | The SQL database foreign key constraint name. Defaults to snake_case{table_name}_{field_name}_fkey. |
fields | [String!] | Foreign key fields. Defaults to{tableName}{PrimaryIdName}. |
references | [String!] | The fields that the foreign key references in the other table. Defaults to its primary key. |
@retired onQUERY |MUTATION |FIELD |VARIABLE_DEFINITION
Marks an element of a GraphQL operation as no longer supported for client use.The Firebase Data Connect backend will continue supporting this element,but it will no longer be visible in the generated SDKs.
| Argument | Type | Description |
|---|---|---|
reason | String | Provides the reason for retirement. |
@searchable onFIELD_DEFINITION
Put on aString field to include it in the full-text search index.
Example
typePost@table{title:String@searchablebody:String@searchable}querySearchPosts($query:String!)@auth(level:PUBLIC){posts_search(query:$query){idtitlebody}}| Argument | Type | Description |
|---|---|---|
language | String | Language of the string column to be indexed for full-text search. (e.g. "french", "spanish", etc.) Defaults to "english" if not specified. |
@table onOBJECT
Defines a relational database table.
In this example, we defined one table with a field namedmyField.
typeTableName@table{myField:String}Data Connect adds an implicitid primary key column. So the above schema is equivalent to:
typeTableName@table(key:"id"){id:String@default(expr:"uuidV4()")myField:String}Data Connect generates the following SQL table and CRUD operations to use it.
CREATETABLE"public"."table_name"("id"uuidNOTNULLDEFAULTuuid_generate_v4(),"my_field"textNULL,PRIMARYKEY("id"))- You can lookup a row:
query ($id: UUID!) { tableName(id: $id) { myField } } - You can find rows using:
query tableNames(limit: 20) { myField } - You can insert a row:
mutation { tableName_insert(data: {myField: "foo"}) } - You can update a row:
mutation ($id: UUID!) { tableName_update(id: $id, data: {myField: "bar"}) } - You can delete a row:
mutation ($id: UUID!) { tableName_delete(id: $id) }
Customizations
@table(singular)and@table(plural)can customize the singular and plural name.@table(name)can customize the Postgres table name.@table(key)can customize the primary key field name and type.
For example, theUser table often has auid as its primary key.
typeUser@table(key:"uid"){uid:String!name:String}- You can securely lookup a row:
query { user(key: {uid_expr: "auth.uid"}) { name } } - You can securely insert a row:
mutation { user_insert(data: {uid_expr: "auth.uid" name: "Fred"}) } - You can securely update a row:
mutation { user_update(key: {uid_expr: "auth.uid"}, data: {name: "New Name"}) } - You can securely delete a row:
mutation { user_delete(key: {uid_expr: "auth.uid"}) }
@table type can be configured further with:
- Custom SQL data types for columns. See
@col. - Add SQL indexes. See
@index. - Add SQL unique constraints. See
@unique. - Add foreign key constraints to define relations. See
@ref.
| Argument | Type | Description |
|---|---|---|
name | String | Configures the SQL database table name. Defaults to snake_case liketable_name. |
singular | String | Configures the singular name. Defaults to the camelCase liketableName. |
plural | String | Configures the plural name. Defaults to infer based on English plural pattern liketableNames. |
key | [String!] | Defines the primary key of the table. Defaults to a single field namedid. If not present already, Data Connect adds an implicit fieldid: UUID! @default(expr: "uuidV4()"). |
@transaction onMUTATION
Require that this mutation always run in a DB transaction.
Mutations with@transaction are guaranteed to either fully succeed or fullyfail. Upon the first error in a transaction (either an execution error or failed@check), the transaction will be rolled back. In the GraphQL response, allfields within the transaction will benull, each with an error raised.
- Fields that have been already evaluated will be nullified due to the rollbackand a "(rolled back)" error will be reported on each of them.
- The execution error or failed
@checkwill be reported on the current field. - Subsequent fields will not be executed. An
(aborted)error will be reportedon each subsequent field.
Mutations without@transaction would execute each root field one afteranother in sequence. They surface any errors as partialfield errors,but does not impact the execution of subsequent fields. However, failed@checks still terminate the entire operation.
The@transaction directive cannot be added to queries for now.Currently, queries cannot fail partially, the response data is not guaranteedto be a consistent snapshot.
@unique onFIELD_DEFINITION |OBJECT
Defines unique constraints on@table.
For example,
typeUser@table{phoneNumber:Int64@unique}typeUserProfile@table{user:User!@uniqueaddress:String@unique}@uniqueon a@colfield adds a single-column unique constraint.@uniqueon a@tabletype adds a composite unique constraint.@uniqueon a@refdefines a one-to-one relation. It adds unique constrainton@ref(fields).
@unique ensures those fields can uniquely identify a row, so other@tabletype may define@ref(references) to refer to fields that has a unique constraint.
| Argument | Type | Description |
|---|---|---|
indexName | String | Configures the SQL database unique constraint name. If not overridden, Data Connect generates the unique constraint name: -table_name_first_field_second_field_uidx -table_name_only_field_name_uidx |
fields | [String!] | Only allowed and required when used on OBJECT, this specifies the fields to create a unique constraint on. |
@view onOBJECT
Defines a relational database Raw SQLview.
Data Connect generates GraphQL queries with WHERE and ORDER BY clauses.However, not all SQL features has native GraphQL equivalent.
You can writean arbitrary SQL SELECT statement. Data Connectwould map Graphql fields on@view type to columns in your SELECT statement.
- Scalar GQL fields (camelCase) should match a SQL column (snake_case)in the SQL SELECT statement.
- Reference GQL field can point to another
@tabletype. Similar to foreign keydefined with@refon a@tabletype, a@viewtype establishes a relationwhen@ref(fields)match@ref(references)on the target table.
In this example, you can use@view(sql) to define an aggregation view on existingtable.
typeUser@table{name:Stringscore:Int}typeUserAggregation@view(sql:"""SELECTCOUNT(*)ascount,SUM(score)assum,AVG(score)asaverage,PERCENTILE_CONT(0.5)WITHINGROUP(ORDERBYscore)ASmedian,(SELECTidFROM"user"LIMIT1)asexample_idFROM"user""""){count:Intsum:Intaverage:Floatmedian:Floatexample:UserexampleId:UUID}Example: Query Raw SQL View
query{userAggregations{countsumaveragemedianexampleIdexample{id}}}One-to-One View
An one-to-one companion@view can be handy if you want to argument a@tablewith additional implied content.
typeRestaurant@table{name:String!}typeReview@table{restaurant:Restaurant!rating:Int!}typeRestaurantStats@view(sql:"""SELECTrestaurant_id,COUNT(*)ASreview_count,AVG(rating)ASaverage_ratingFROMreviewGROUPBYrestaurant_id"""){restaurant:Restaurant@uniquereviewCount:IntaverageRating:Float}In this example,@unique convey the assumption that eachRestaurant shouldhave only oneRestaurantStats object.
Example: Query One-to-One View
queryListRestaurants{restaurants{namestats:restaurantStats_on_restaurant{reviewCountaverageRating}}}Example: Filter based on One-to-One View
queryBestRestaurants($minAvgRating:Float,$minReviewCount:Int){restaurants(where:{restaurantStats_on_restaurant:{averageRating:{ge:$minAvgRating}reviewCount:{ge:$minReviewCount}}}){name}}Customizations
- One of
@view(sql)or@view(name)should be defined.@view(name)can refer to a persisted SQL view in the Postgres schema. @view(singular)and@view(plural)can customize the singular and plural name.
@view type can be configured further:
@uniquelets you define one-to-one relation.@collets you customize SQL column mapping. For example,@col(name: "column_in_select").
Limitations
Raw SQL view doesn't have a primary key, so it doesn't support lookup. Other@table or@view cannot have@ref to a view either.
View cannot be mutated. You can perform CRUD operations on the underlyingtable to alter its content.
Important: Data Connect doesn't parse and validate SQL
- If the SQL view is invalid or undefined, related requests may fail.
- If the SQL view return incompatible types. Firebase Data Connect may surfaceerrors.
- If a field doesn't have a corresponding column in the SQL SELECT statement,it will always be
null. - There is no way to ensure VIEW to TABLE
@refconstraint. - All fields must be nullable in case they aren't found in the SELECT statementor in the referenced table.
Important: You should always test@view!
| Argument | Type | Description |
|---|---|---|
name | String | The SQL view name. If neithername norsql are provided, defaults to the snake_case of the singular type name.name andsql cannot be specified at the same time. |
sql | String | SQLSELECT statement used as the basis for this type. SQL SELECT columns should use snake_case. GraphQL fields should use camelCase.name andsql cannot be specified at the same time. |
singular | String | Configures the singular name. Defaults to the camelCase likeviewName. |
plural | String | Configures the plural name. Defaults to infer based on English plural pattern likeviewNames. |
Built In
@deprecated onFIELD_DEFINITION |ARGUMENT_DEFINITION |INPUT_FIELD_DEFINITION |ENUM_VALUE
Marks an element of a GraphQL schema as no longer supported.
| Argument | Type | Description |
|---|---|---|
reason | String | Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified byCommonMark. |
@include onFIELD |FRAGMENT_SPREAD |INLINE_FRAGMENT
Directs the executor to include this field or fragment only when theif argument is true.
| Argument | Type | Description |
|---|---|---|
if | Boolean! | Included when true. |
@skip onFIELD |FRAGMENT_SPREAD |INLINE_FRAGMENT
Directs the executor to skip this field or fragment when theif argument is true.
| Argument | Type | Description |
|---|---|---|
if | Boolean! | Skipped when true. |
@specifiedBy onSCALAR
Exposes a URL that specifies the behavior of this scalar.
| Argument | Type | Description |
|---|---|---|
url | String! | The URL that specifies the behavior of this scalar. |
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2026-01-21 UTC.