Catalogs
BigQuery

BigQuery

catalog.dataset.table

What you need

FieldNotes
Project idThe project holding the data
DatasetPin this. See below
Service account keyJSON, pasted once
Billing projectOptional, if queries should bill elsewhere
Read-onlyOptional

Only the service-account email is kept in the clear, so you can see which identity a catalog runs as; the key itself goes to the secrets manager.

Always pin the dataset

An unpinned catalog enumerates every dataset and table in the project the first time a query is planned. Measured against one real project: 62 seconds and 1.27 GiB to plan, versus 0.9 seconds and 164 MiB with the dataset set. Because planning happens in a fresh process per submission, that cost is paid on every query — it reads to users as a hang.

One catalog per dataset is the rule.

IAM the identity actually needs

Reads go through the BigQuery Storage Read API, which is not covered by dataViewer alone:

RoleScopeWhy
roles/bigquery.dataViewerdatasetread the tables
roles/bigquery.jobUserprojectrun a query at all
roles/bigquery.readSessionUserprojectcreate a read session

Missing the last one produces the user does not have 'bigquery.readsessions.create' permission, and it blocks metadata collection as well as queries. readsessions.create cannot be granted at dataset scope.

To write, add roles/bigquery.dataEditor on the dataset and leave the catalog writable.