Notion to BigQuery: How to Move Your Data

Sync Notion to BigQuery with Airbyte. Why shared pages decide what you get, the Data Sources rename in v4.0.0, rate limits, and the Blocks stream.

Summarize with AI:

Syncing Notion to BigQuery moves pages, blocks, comments, and structured tables out of a workspace and into a warehouse where they can be queried with SQL and joined against operational data. Teams do this to analyse project trackers, content pipelines, and internal documentation that only exists in Notion. Airbyte handles the extraction with no code.

One setup step causes more confusion than everything else combined, and it happens in Notion rather than in Airbyte. The connector can only read pages that have been explicitly shared with your integration.

CapabilityWhat it means for this pipeline
Page accessOnly pages shared with the integration are visible
Rate limitAbout three requests per second per integration
Rate limit behaviourRetries do not count toward the retry limit, so syncs wait it out
Blocks nestingChild blocks are fetched recursively up to 30 levels deep
Default start dateTwo years back if you leave the field blank

Why is my sync returning almost nothing?

The Notion source retrieves page objects from all shared pages. That word shared is doing a great deal of work. Creating the integration and pasting the token into Airbyte grants access to nothing by default. Each page or top-level section must be connected to the integration from within Notion.

So a successful connection test followed by a near-empty sync is the expected outcome of a half-finished setup, not a bug. Share the top-level pages you care about, and remember that sharing cascades to children, which means one well-chosen parent page is usually easier to maintain than twenty individual ones.

You must be the owner of the Notion workspace to create an integration associated with it, and the Users stream additionally requires the Read user information capability to be enabled on the integration. If that capability is missing, the stream comes back empty rather than raising a permissions error.

Authentication is by OAuth2.0 or an access token. There is also a start date, and if you leave it blank Airbyte defaults to two years before the current date, which is worth knowing if you expected a full historical load and got a partial one.

The Databases stream is now Data Sources

Notion changed its terminology and the connector followed. In the Notion API version dated 2025-09-03, a data source represents a structured table containing pages and properties, which is what used to be called a database. As of connector version 4.0.0, the Data Sources stream replaces the former Databases stream.

If you are upgrading an existing connection rather than starting fresh, follow the connector's migration guide, and check any downstream models referencing the old stream name before the upgrade rather than after. An earlier migration of this connector from the Python CDK to the low-code framework was also a breaking change for the Comments stream, because state management for incremental streams nested within a parent stream was restructured. Both are the kind of change that surfaces as a confusing partial sync if you upgrade without reading.

Note also that the Users stream does not support incremental append. For a small, slowly changing stream that is no real loss, but it is worth knowing before you configure sync modes stream by stream.

Rate limits and the Blocks stream

The Notion API enforces a rate limit of roughly three requests per second per integration. When the connector receives an HTTP 429 it honours the Retry-After header and retries automatically, and importantly, rate-limited requests do not count toward the maximum retry limit. Syncs therefore continue until the limit clears rather than failing.

That is good behaviour, but it has the same consequence as GitHub's: a sync that appears to hang is often just waiting. Airbyte's documentation notes the connector should not run into API limitations under normal usage, so persistent throttling is a signal that your selection is too broad rather than something to work around.

The Blocks stream is where breadth turns into volume. It recursively fetches child blocks up to 30 levels deep, and in Notion every paragraph, bullet, and toggle is a block. A modestly sized workspace produces a very large Blocks table, and at three requests per second that takes real time. Select the stream only if you genuinely need block-level content, and consider whether the Pages and Data Sources streams already answer your question.

Landing the data in BigQuery

The BigQuery destination uses direct load and writes straight to final tables, with Batched Standard Inserts as the default. Your service account needs BigQuery User and BigQuery Data Editor, and the dataset location must match the datasets you will join against, since BigQuery cannot query across locations and the location is fixed at creation.

Notion's data model is the challenge on arrival. Page properties are a flexible key-value structure where each property carries its own type, and a property that is a select in one database is a multi-select in another. Rich text is a nested array of objects with formatting annotations rather than a plain string. All of that lands as structured JSON.

Because Notion schemas are edited by whoever uses the workspace, treat the landed tables as raw and build a model that extracts the specific properties you report on. Renaming a property in Notion should break one definition you own rather than every dashboard at once.

Frequently asked questions

My connection works but almost no data arrives.

The connector reads only pages shared with your integration. Connect the relevant top-level pages to the integration inside Notion, and sharing will cascade to their children.

Where did the Databases stream go?

It was replaced by Data Sources as of connector version 4.0.0, following Notion's own terminology change. Follow the migration guide if you are upgrading an existing connection.

Why is the Users stream empty?

It requires the Read user information capability on the integration. Enable it in the integration's Capabilities settings in Notion and re-sync.

Why is my sync so slow?

Notion allows roughly three requests per second per integration, and the Blocks stream recurses up to 30 levels deep. Deselect Blocks unless you need block-level content.

Get your Notion data into BigQuery

Share the right pages with your integration first, set a start date deliberately, leave Blocks unselected unless you need it, and model over the raw property JSON. For the general pattern of loading API data, see our guide to API to database. For a relational source into the same warehouse, see PostgreSQL to BigQuery.

Start syncing now →

Integrate with 600+ apps using Airbyte

Move data from 600+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.