ServicesAboutNotesContact Get in touch →
EN FR
Note

BigQuery Cross-Organization Data Sharing

Patterns for sharing BigQuery data across organizations — agency/client models, Analytics Hub, authorized views, and row/column-level security.

Planted
bigquerygcpdata engineering

BigQuery provides several mechanisms for sharing data across organizational boundaries, each suited to different trust models and data sensitivity requirements. This note covers the agency/client pattern, Analytics Hub, authorized views, and row/column-level security.

Agency/Client Pattern: Work in Client Organizations

The recommended pattern for agencies and consultancies: each client owns their GCP organization. The agency gets access as needed.

Client Alpha Organization (owned by client)
├── client-alpha-analytics
│ └── All BigQuery resources, dbt models, data
└── IAM: Agency team granted access
Client Beta Organization (owned by client)
├── client-beta-analytics
│ └── All BigQuery resources, dbt models, data
└── IAM: Agency team granted access
Agency Organization (agency-owned)
└── agency-internal
└── Internal tooling, templates, documentation only

This provides clear data ownership. Client data stays in client infrastructure. When engagements end, clients retain full control without data migration. Billing flows naturally to client accounts. Compliance requirements are the client’s responsibility to define and the agency’s responsibility to follow.

The agency team authenticates to each client organization separately. Maintain separate service accounts per client, separate credentials, separate dbt profiles. This adds overhead but prevents cross-client data leakage and keeps audit trails clean.

Fallback: Project-per-Client in Agency Organization

Some clients can’t or won’t maintain their own GCP organization — small businesses without IT infrastructure, short-term engagements, or clients who explicitly want the agency to handle everything.

Agency Organization
├── agency-admin
│ └── Audit logs, billing exports, shared tooling
├── client-alpha-analytics
│ └── All BigQuery resources for Client Alpha
└── client-beta-analytics
└── All BigQuery resources for Client Beta

This pattern requires extra care. Document clearly that the agency owns the infrastructure. Define data ownership and export rights in contracts. Plan for offboarding: if a client wants to leave, you’ll need to export their data and potentially migrate their dbt project to their own organization.

Use labels and separate projects to track costs accurately per client. Billing can flow to the client’s billing account (linked to the agency project) or the agency can invoice based on costs.

Analytics Hub for Formal Data Sharing

Analytics Hub enables zero-copy data sharing across organizational boundaries. It’s the right tool when you need structured, auditable sharing with clear publisher/subscriber roles.

A data owner publishes a dataset to an Analytics Hub listing. Subscribers in other organizations request access. Once approved, they get a linked dataset — a read-only reference that points to the source data without copying it.

Key characteristics:

  • Storage costs stay with the publisher. Query costs go to the subscriber.
  • Subscribers cannot modify data, cannot set IAM on individual tables, cannot do anything except read.
  • Publishers can restrict data egress entirely, blocking EXPORT, CREATE TABLE AS SELECT, and copy operations.
  • All access is logged for auditing.

For agency work, create a private exchange within Analytics Hub. Add specific principals (users, groups, or service accounts) as subscribers. Clients subscribe to listings and query through their linked datasets.

Analytics Hub is particularly useful when the data relationship is truly one-directional: a data provider shares curated datasets with consumers who should only read, never modify. For bidirectional collaboration (where both parties create and share data), the separate-organization patterns above are more appropriate.

Authorized Views for Controlled Access

Authorized views solve a common problem: exposing filtered or aggregated data without granting access to underlying tables. They work across organizational boundaries.

The pattern:

  1. Create a view in a dedicated dataset that queries sensitive source tables
  2. Authorize the view’s dataset to access the source dataset
  3. Grant users access to the view dataset only
-- In dataset: shared_views
CREATE VIEW shared_views.analyst_orders AS
SELECT
order_id,
order_date,
total_amount
-- customer_ssn excluded
-- internal_notes excluded
FROM sensitive_data.mrt__sales__orders
WHERE region = 'EMEA'; -- Row filtering

The view references sensitive_data.mrt__sales__orders, but users only need access to shared_views. In BigQuery’s console, you authorize shared_views to access sensitive_data. Anyone who can query shared_views.analyst_orders gets the filtered, column-restricted view without any permissions on sensitive_data.

Authorized datasets extend this concept. Instead of authorizing individual views, you authorize an entire dataset. All current and future views in that dataset can access the source data. This reduces management overhead when you’re creating many views for different access patterns.

Authorized views are the simplest mechanism for column-filtering and row-filtering use cases. They don’t require Analytics Hub infrastructure and work within a single project or across projects.

Row-Level and Column-Level Security

For truly multi-tenant environments where different users see different rows of the same table, BigQuery offers row-level security:

CREATE ROW ACCESS POLICY client_a_only
ON multi_tenant.mrt__shared__orders
GRANT TO ('group:client-a-analysts@clienta.com')
FILTER USING (client_id = 'CLIENT_A');
CREATE ROW ACCESS POLICY client_b_only
ON multi_tenant.mrt__shared__orders
GRANT TO ('group:client-b-analysts@clientb.com')
FILTER USING (client_id = 'CLIENT_B');

Client A analysts querying multi_tenant.mrt__shared__orders see only their rows. Client B sees only theirs. The table is the same; the access differs. This is transparent to the query — users don’t need to add WHERE client_id = ... clauses, and they can’t bypass the filter even if they try.

Column-level security uses Data Catalog policy tags. You create a tag (say, PII), apply it to sensitive columns, then grant specific users the Fine-Grained Reader role for that tag. Users without the role see those columns as null or receive access errors.

Dynamic data masking takes this further. Users with Masked Reader role see hashed or partially redacted values instead of nulls. Useful for scenarios where analysts need to see that a value exists and can join on it, but shouldn’t see the actual content — think hashed email addresses for matching across datasets without exposing PII.

Choosing the Right Mechanism

MechanismBest forComplexityCross-org?
Authorized viewsColumn/row filtering within projectsLowYes
Authorized datasetsMany views needing source accessLowYes
Analytics HubFormal publisher/subscriber sharingMediumYes
Row-level securityMulti-tenant same-table accessMediumYes
Column-level securityPII protection across consumersMediumYes
Separate projectsFull isolation per client/teamHighN/A

Start with the simplest mechanism that meets your requirements. Authorized views handle most cases. Row-level security adds value when you can’t separate tenants into different datasets. Analytics Hub adds value when you need formal governance over who can subscribe to what.