Directives

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.

ArgumentTypeDescription
levelAccessLevelThe minimal level of access required to perform this operation. Exactly one oflevel andexpr should be specified.
exprBoolean_ExprA CEL expression that grants access to this operation if the expression evaluates totrue. Exactly one oflevel andexpr should be specified.
insecureReasonStringIf 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.

ArgumentTypeDescription
exprBoolean_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.)
messageString!The error message to return to the client if the check fails. Defaults to "permission denied" if not specified.
optionalBooleanWhether 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.

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)}
ArgumentTypeDescription
nameStringThe SQL database column name. Defaults to snake_case of the field name.
dataTypeStringConfigures 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.
sizeIntRequired 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.

ArgumentTypeDescription
valueAnyA constant value validated against the field's GraphQL type during compilation.
exprAny_ExprA CEL expression whose return value must match the field's data type.
sqlAny_SQLA 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.

ArgumentTypeDescription
nameStringConfigure 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.
typeIndexTypeCustomize the index type. For most index, it defaults toBTREE. For array fields, only allowedIndexType isGIN. ForVector fields, defaults toHNSW, may configure toIVFFLAT.
vector_methodVectorSimilarityMethodOnly 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_fkey above).
  • @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@ref table.Other fields with@unique may also be referred in the foreign key constraint.
ArgumentTypeDescription
constraintNameStringThe 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.

ArgumentTypeDescription
reasonStringProvides 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}}
ArgumentTypeDescription
languageStringLanguage 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.
ArgumentTypeDescription
nameStringConfigures the SQL database table name. Defaults to snake_case liketable_name.
singularStringConfigures the singular name. Defaults to the camelCase liketableName.
pluralStringConfigures 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@check will 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}
  • @unique on a@col field adds a single-column unique constraint.
  • @unique on a@table type adds a composite unique constraint.
  • @unique on a@ref defines 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.

ArgumentTypeDescription
indexNameStringConfigures 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@table type. Similar to foreign keydefined with@ref on a@table type, a@view type 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:

  • @unique lets you define one-to-one relation.
  • @col lets 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 benull.
  • There is no way to ensure VIEW to TABLE@ref constraint.
  • 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!

ArgumentTypeDescription
nameStringThe 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.
sqlStringSQLSELECT 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.
singularStringConfigures the singular name. Defaults to the camelCase likeviewName.
pluralStringConfigures 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.

ArgumentTypeDescription
reasonStringExplains 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.

ArgumentTypeDescription
ifBoolean!Included when true.

@skip onFIELD |FRAGMENT_SPREAD |INLINE_FRAGMENT

Directs the executor to skip this field or fragment when theif argument is true.

ArgumentTypeDescription
ifBoolean!Skipped when true.

@specifiedBy onSCALAR

Exposes a URL that specifies the behavior of this scalar.

ArgumentTypeDescription
urlString!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.