SharePoint to Google BigQuery

Load SharePoint lists into a BigQuery dataset with a service account, then query them from Looker Studio, notebooks or dbt.

Book a call

Talk through your use case, see further walkthroughs or demos, and set up a trial in your own environment.

Last updated

One way: SharePoint stays the system of record, and SPSync keeps a read-only copy of your lists current in Google BigQuery.

Status: Shipped · product: SPSync for Warehouses & Lakes

On Google Cloud, BigQuery is often where the rest of an organisation’s data already lives. Replicating SharePoint lists there puts them in the same SQL as everything else: Looker Studio and Looker dashboards, scheduled queries, notebooks and dbt models, with no cluster to size for the replication itself.

The service account and the dataset

BigQuery has no connection string. SPSync reads the service account’s downloaded JSON key from an environment variable, so the key never appears in the configuration file. Grant that account two roles:

The destination’s dataset name is the whole namespace. If the dataset does not exist, SPSync creates it in the service account’s own project, in the region you set, US unless you choose another such as EU or europe-west2. A dataset that already exists keeps its region. Datasets in a different project are not supported.

How rows arrive

Each list becomes a table in that dataset, for example hr_leave_requests, with child tables such as hr_leave_requests__approvers for multi-value columns and one sp_users table for people. Lookups arrive as {col}_id and {col}_value. Text of every length is STRING, whole numbers are INT64, currency is NUMERIC(38,9), timestamps are UTC TIMESTAMP and JSON-shaped values use BigQuery’s native JSON type.

After the first load, each run merges changed rows with BigQuery’s MERGE statement. Deleted items stay with sp_deleted_at set, and the command-line tool’s hard delete setting issues a plain DELETE instead. Optional reporting views are available here too. A new SharePoint column appears on the next run and a removed one stays; a retyped column is not forked into a _v2 column on BigQuery today (SPSync does that on SQL Server, PostgreSQL, MySQL, ClickHouse, Oracle, SQLite and DuckDB).

Typical uses

KPI dashboards in Looker Studio or Looker read the tables on the sync schedule, with no spreadsheet export in between. dbt models add the dataset as another source. Data preparation for models starts from typed, deduplicated rows. A set of extraction scripts run by hand becomes one replication that is reviewed in a pull request.

Limits to know

Setting it up

  1. Sign in with delegated access, or have an admin register an app with Sites.Selected on the sites you need for unattended runs.
  2. Create the service account, grant the two roles and download its key.
  3. Put the key in an environment variable and set the dataset name and region.
  4. Select the lists or a whole site, then run.
  5. Connect Looker Studio, Looker or a notebook to the dataset.

BigQuery bills storage and query bytes scanned separately from SPSync.

Desktop, Azure or command line

All three editions run the same engine, write the same tables and use the same licence key, so the choice comes down to who looks after the sync.

Desktop app

For macOS and Windows. Sign in with Microsoft, tick the lists, choose a database and sync from your own machine on the schedule you set. Delegated sign-in needs no admin unless your tenant requires admin consent for apps.

In your Azure

SPSync in your Azure, a managed application for your own subscription, is deployed with you on a call while the Marketplace listing is prepared. Once deployed it is always on, so the sync keeps running with every laptop closed.

Command line

Every replication is a YAML file you can review and commit. Run it from a server, a container or a CI pipeline, and re-run it safely any time.

Frequently asked questions

How does SPSync authenticate to BigQuery?

With a Google Cloud service account. You put the whole downloaded JSON key in an environment variable, and SPSync reads it from there. BigQuery has no connection string.

Which roles does the service account need?

BigQuery Data Editor on the project or dataset, to create tables and write rows, and BigQuery Job User, to run the load and query jobs. It needs no project-level admin role.

Are multi-value columns stored as ARRAY or STRUCT fields?

No. A multi-choice column becomes a child table with one row per value, the same as on every other destination, and no nested ARRAY copy is written. Multi-lookup and multi-person values are still being verified on a live tenant.

Does each run rebuild the whole table?

No. Each run merges the changed rows into the table with BigQuery's MERGE statement, so the work done tracks the size of the change. A first load and a reconcile, weekly by default, read the whole list again.

What happens to items deleted in SharePoint?

The row stays and its sp_deleted_at column is set, so a report can show deleted items or filter them out. To remove the row instead, set deletes: hard on that replication in the command-line tool's YAML config. Runs from the desktop app and from SPSync in your Azure always keep the row.

Talk to us about Google BigQuery

SPSync is licensed per installation and per target family, with Standard Support included. Tell us which targets you need and how many machines, and we will size it with you. See how licensing works.

Set it up

Sign in to SharePoint with the SharePoint connection guide, then follow the Google BigQuery setup guide to create the database user and open the connection for Google BigQuery. If the connection test fails, the troubleshooting guide lists the errors people hit and what fixes them.

Script it

Everything you can click, you can script. The CLI, YAML config and automation below reproduce this scenario exactly. See the CLI reference.

spsync auth login --client-id 00000000-0000-0000-0000-000000000000
spsync export-config --output replication.yaml --pipeline-name bigquery --prefix bigquery --destination-kind bigquery --connection-string-env SPSYNC_DB_CONNECTION --dataset-name bigquery --client-id 00000000-0000-0000-0000-000000000000 --site-url https://contoso.sharepoint.com/sites/example --all-lists
spsync doctor replication.yaml
spsync run replication.yaml
pipeline_name: bigquery
prefix: bigquery
auth:
  mode: delegated
  client_id: 00000000-0000-0000-0000-000000000000
  tenant_id: common
destination:
  kind: bigquery
  connection_string_env: SPSYNC_DB_CONNECTION
  dataset_name: bigquery
scopes:
  - site_url: https://contoso.sharepoint.com/sites/example
    mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false

Cron (BigQuery nightly):

# every night at 02:00
0 2 * * * cd /opt/spsync && SPSYNC_DB_CONNECTION="$(cat /etc/spsync/db.env)" uv run spsync run replication.yaml >> /var/log/spsync/run.log 2>&1

GitHub Actions:

# .github/workflows/spsync-run.yml
name: SPSync
on:
  schedule:
    - cron: "0 2 * * *"
  workflow_dispatch: {}
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v3
      - run: uv sync
      - run: uv run spsync run replication.yaml
        env:
          SPSYNC_DB_CONNECTION: ${{ secrets.SPSYNC_DB_CONNECTION }}
          SPSYNC_LICENCE_KEY: ${{ secrets.SPSYNC_LICENCE_KEY }}

Azure DevOps:

# azure-pipelines.yml
schedules:
  - cron: "0 2 * * *"
    branches: { include: [main] }
    always: true
steps:
  - script: uv sync
  - script: uv run spsync run replication.yaml
    env:
      SPSYNC_DB_CONNECTION: $(SPSYNC_DB_CONNECTION)
      SPSYNC_LICENCE_KEY: $(SPSYNC_LICENCE_KEY)

Windows (PowerShell + Task Scheduler):

# Windows Task Scheduler action (see /docs/cli/automation/)
$env:SPSYNC_DB_CONNECTION = (Get-Content C:\spsync\db.env)
uv run spsync run C:\spsync\replication.yaml
schtasks /Create /SC DAILY /ST 02:00 /TN "SPSync" /TR "powershell -File C:\spsync\run.ps1"

macOS (launchd):

# ~/Library/LaunchAgents/io.spsync.run.plist, then: launchctl load ~/Library/LaunchAgents/io.spsync.run.plist

Secrets (licence key, connection strings) come from the environment, so never write them into the YAML. See scheduling and secrets.

Book a call

Tell us about your lists and where they need to go: we will talk through your use case, show further walkthroughs or demos, and set up a trial in your own environment.