BigQuery access for multi-tenant Bubble analytics: row policies, authorized views, or separate tables?

A shared analytical warehouse routes data through three governed patterns: filtered rows, a restricted view, and separate tenant table stacks.

The short answer

Choose the access pattern from who runs the query and how strongly tenants must be isolated. Row-level access policies are useful when recognized Google Cloud principals query a shared table and need different row subsets. Authorized views are useful when you want to share a curated query result without granting access to the source dataset. Separate tenant tables or datasets provide a stronger physical administration boundary, but they increase provisioning, schema, and operational work.

None of these choices fixes a bad tenant mapping. Carry one stable, trusted tenant identifier from Bubble into the warehouse, validate it during ingestion, and test that every access path returns only the intended rows. If customers do not query BigQuery directly, it may be safer to keep BigQuery behind an application service that authorizes the Bubble user and runs bounded server-side queries.

This article narrows one issue from the broader Bubble database versus BigQuery decision: once analytical data is in BigQuery, how should different organizations see different slices?

Begin with the query principal

Before choosing a BigQuery feature, identify the principal BigQuery actually sees:

  • an internal analyst using a managed Google identity;

  • a customer employee using an approved federated identity;

  • a dashboard service account shared by many viewers;

  • a backend application that queries on behalf of Bubble users;

  • an export job that writes customer-specific files.

This matters because BigQuery policies evaluate Google Cloud principals, not the Bubble user hidden behind a shared backend credential. If every dashboard request reaches BigQuery as the same service account, a row policy based on SESSION_USER() cannot distinguish two Bubble customers. The application must add a separately enforced tenant filter, use distinct workload identities, or generate tenant-specific governed outputs.

Do not pass a browser-supplied tenant ID into SQL and call that row-level security. Bind the Bubble user to a tenant in trusted application data, resolve that mapping server-side, parameterize queries, and constrain the service account to the minimum datasets and jobs it needs.

Pattern 1: row-level access policies

BigQuery row-level security applies filter expressions to a table so specified users or groups can see only qualifying rows. One shared fact table might contain tenant_id, and policies can grant different principals access to different tenant values.

This pattern can fit an internal analytics environment where identity groups are well managed and many tenants share one schema. Centralized tables simplify ingestion and cross-tenant operations for explicitly authorized administrators. Policies can coexist with dataset, table, and column-level controls.

The operational risks are significant:

  • policy grants must track tenant onboarding and offboarding;

  • a broad TRUE policy can preserve full access for an administrative group;

  • writers and policy administrators need separately reviewed permissions;

  • policy changes require audit monitoring;

  • the query principal must represent the intended viewer;

  • side channels and feature interactions still require review.

Google recommends monitoring Cloud Audit Logs for unexpected policy additions, changes, or deletions and using separate groups for write access and row-policy access. Add negative tests for a user with no matching policy, a user moved between groups, and an administrator who should retain only the access their role requires.

Row policies work poorly when thousands of external customers would require fragile per-customer identity administration, or when one shared service identity queries for everyone. In those cases, use an application boundary or another sharing pattern.

Pattern 2: authorized views

An authorized view is a logical or materialized view that can read source data while its consumers cannot access the source dataset directly. The view query selects rows and columns, derives approved metrics, and presents a smaller contract to analysts or applications.

Google's authorized views guide recommends placing source data and shared views in separate datasets, granting consumers permission to run jobs and access the view dataset, and authorizing the view to read the source dataset.

Authorized views are attractive when the shared interface should be more than a row filter. A view can remove sensitive columns, normalize field names, join reference data, or expose only approved aggregates. That makes it useful for internal teams and stable reporting contracts.

However, a tenant-specific view with a hard-coded tenant filter still creates a provisioning object per tenant. A shared view that accepts no trusted identity cannot decide which Bubble tenant is active. If the application service queries the view, it must still enforce the user's tenant in a bounded parameterized query.

Google notes that authorized views and row policies have different security, flexibility, and performance characteristics, and both require careful handling. Review indirect information exposure, query permissions, metadata visibility, and audit logs. Do not assume that hiding the source dataset makes every query result safe.

Pattern 3: separate tenant tables or datasets

Separate tables or datasets place tenant data into distinct resources. Google describes separate tables as the strongest of the three compared isolation choices because a principal without resource access cannot infer data from the inaccessible table in the same way. This can be valuable for third-party sharing, contractual isolation requirements, or a small number of high-value tenants with materially different retention and access rules.

The cost is operational multiplication. Every schema change, ingestion job, quality check, retention rule, policy binding, and dashboard dependency may need to run across many resources. Cross-tenant administrative analytics require carefully scoped union or aggregate processes. Tenant creation and deletion become infrastructure workflows, not merely row inserts.

Avoid naming datasets from customer display names. Use stable, opaque tenant identifiers and a governed registry. Keep project and dataset quotas in mind, and test provisioning rollback. If one tenant's table fails to update, the pipeline should surface the partial state instead of silently reporting inconsistent metrics.

Separate resources are not a reason to create one broad service account with access to all of them and then expose that identity to customer-facing code. Keep application and administrative identities distinct.

Pattern 4: keep BigQuery behind the application

Many Bubble portals should not give customers direct BigQuery access at all. A backend service can authenticate the Bubble user, derive the tenant from trusted state, execute a bounded parameterized query, and return only the approved result shape. BigQuery remains an analytical engine, while the application owns customer authorization.

This pattern makes the query service a critical security boundary. It needs:

  • a narrow query catalog or validated query builder;

  • parameterized values rather than string concatenation;

  • dataset and table allowlists;

  • maximum bytes, time, and result limits;

  • per-tenant rate and cost controls;

  • audit events without raw customer data;

  • tests proving that supplied tenant values are ignored or checked;

  • consistent deletion and retention behavior.

The service account may need access to shared tables, but that does not authorize callers to select any tenant. Application-level tests must prove that two authenticated Bubble users receive different, correct scopes even though BigQuery sees one backend identity.

Compare the choices

Question

Row policies

Authorized views

Separate resources

Application service

Direct Google principal access

Strong fit

Strong fit

Strong fit

Not required for end user

Shared schema

Yes

Usually

No or partially

Yes

Removes or transforms columns

Pair with column controls

Yes

By schema

Yes

Strong resource isolation

Moderate

Moderate

Highest of these options

Depends on service and IAM

Tenant onboarding effort

Policy/group work

View/grant work

Resource/pipeline work

Application mapping work

Works with one shared backend identity

Does not identify Bubble user by itself

Does not identify Bubble user by itself

Only if service selects correctly

Yes, with enforced server mapping

Cross-tenant admin reporting

Convenient with separate admin access

Convenient through admin views

Requires governed aggregation

Possible through separate admin endpoints

The table is a design aid, not a universal ranking. Regulated data, contractual commitments, threat models, and customer-managed identities may require a specialist review and a different boundary.

Build a trustworthy tenant key

The access layer is only as reliable as tenant_id. Use a stable source ID, not an organization name, email domain, or editable label. Preserve the original Bubble record identifier or map it to an opaque warehouse key through a versioned registry. Every ingested fact should receive its tenant association from a trusted source record or verified join.

Test for null tenant IDs, unknown IDs, conflicting mappings, late updates, merges, and deleted organizations. Quarantine rows that cannot be assigned safely. A default “shared” tenant is dangerous because mapping errors can turn into data exposure.

The related guide Moving relational Bubble data into BigQuery covers stable IDs, relationships, deletes, and schema drift in more depth.

A two-tenant negative test

Use synthetic organizations, such as Harbor and Cedar, with deliberately similar records:

  1. load three Harbor rows and three Cedar rows with stable tenant IDs;

  2. add one unmapped row that should be quarantined;

  3. query as the Harbor principal or authorized application request;

  4. confirm that no Cedar values, row counts, or metadata leak;

  5. attempt direct source-table access and expect denial where the pattern requires it;

  6. repeat as Cedar;

  7. repeat as an explicitly authorized cross-tenant administrator;

  8. change one group, view grant, or application mapping and verify the audit event;

  9. export results and confirm the same scope is preserved;

  10. remove access and confirm cached dashboards or extracts follow the documented revocation behavior.

Test aggregates as well as raw rows. A count, minimum date, error message, or query-timing difference can disclose information even when individual records are hidden. Google's row-level security documentation discusses potential side channels and recommends audit monitoring.

Operational checklist

  • Identify the principal BigQuery sees for every query path.

  • Document whether customers have direct BigQuery access.

  • Use one stable, validated tenant key.

  • Quarantine unmapped records.

  • Separate data writers, policy administrators, and report readers.

  • Grant job execution and data access deliberately; they are different permissions.

  • Monitor changes to policies, views, datasets, and IAM.

  • Bound query cost and result size for application-mediated access.

  • Test two tenants, an unmapped row, and an administrator.

  • Verify exports, dashboards, caches, and downstream copies.

  • Reconcile tenant deletion and retention across Bubble and BigQuery.

  • Review the choice again when tenant count, identity model, or contractual requirements change.

The design decision

Use row policies when managed principals query shared tables and policy administration is tractable. Use authorized views when consumers need a curated relational interface without source-dataset access. Use separate tables or datasets when stronger resource isolation justifies operational duplication. Keep BigQuery behind an application service when the real end user is a Bubble identity and the application must make the tenant decision.

Whichever pattern you choose, prove the negative case. The goal is not a clean dashboard. It is evidence that Harbor cannot observe Cedar through rows, columns, aggregates, exports, or an incorrectly shared service identity.

Primary keyword: BigQuery multi-tenant row-level security

Primary CTA: Describe who runs your BigQuery queries and how tenants authenticate.

Sources checked: BigQuery row-level security, BigQuery authorized views, row-level security best practices, and using row-level security with other features, checked 2026-10-02.

Help shape the cloud layer for Bubble apps

Help shape the cloud layer for Bubble apps

Help shape the cloud layer for Bubble apps

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.

Bubble2X is building a Bubble-to-Google-Cloud integration for controlled customer-file workflows.

Newsletter

Get tips, product updates, and insights about building with Bubble2X.

Subscribe to Bubble2X updates. See our Privacy Notice.

© 2026 Bubble2X. Product in development.