SharePoint to Google Cloud SQL (SQL Server, Postgres, MySQL)

Cloud SQL for PostgreSQL, MySQL or SQL Server as a home for SharePoint lists, through the Cloud SQL Auth Proxy or a direct TLS connection.

Book a call

Book a call to 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 Cloud SQL.

Status: Shipped · product: SPSync for Relational Databases

Getting SharePoint lists into Cloud SQL tends to stall on the connection, not the data: a public IP that refuses every address until you authorise it, a proxy to run, and an SSL mode that decides which certificate files the client must present. Once the connection works, SPSync writes the same tables it would write to PostgreSQL, MySQL or SQL Server on any other host, and Looker, Power BI or your Google Cloud app reads them with its usual driver. The PostgreSQL engine gets the most detail below, with notes where MySQL or SQL Server on Cloud SQL differ.

How do I connect SPSync to Cloud SQL?

The Cloud SQL Auth Proxy. Run it on the machine that runs the sync and point the connection string at 127.0.0.1 on the engine’s port: 5432 for PostgreSQL, 3306 for MySQL, 1433 for SQL Server. Leave the TLS options out, since the proxy handles encryption and uses IAM to authorise itself. The proxy’s service account needs the Cloud SQL Client role on the project.

A private IP. From a VM or container inside the VPC, or a network connected through private services access or Private Service Connect, connect straight to the instance’s private address.

A public IP with authorised networks. Add the sync host’s address to the instance’s authorised networks and connect directly. This is the route where the instance’s SSL mode matters most.

In every case SPSync logs in with a database username and password read from an environment variable. IAM database authentication is not supported.

SSL modes and the connection string

A Cloud SQL instance has one of three SSL modes, and a direct connection has to match it:

Instance SSL modePostgreSQL connection stringMySQLSQL Server
Allow unencrypted and encrypted (the default)sslmode=require to encrypt anywayssl_ca with the server CAEncrypt=yes
Encrypted onlysslmode=requiressl_ca with the server CAEncrypt=yes
Trusted client certificate requiredsslmode=verify-ca with sslrootcert, sslcert and sslkeyssl_ca, ssl_cert and ssl_keyNot offered for SQL Server

The default accepts unencrypted connections, so a sync over a public IP is only encrypted if its string asks for it. Through the Auth Proxy none of this applies: the proxy encrypts the hop to the instance whatever the mode. The certificate files live on the sync host; the connection string, with their paths, goes in the environment variable.

SPSync writes to Cloud SQL through the same PostgreSQL, MySQL and SQL Server destinations it uses on other hosts, and its automated tests run those engines in containers. The Cloud SQL routes and SSL modes above come from Google’s documentation, so prove the route from the sync host with psql, mysql or sqlcmd before the first run.

A database user for each engine

The default admin users can do far more than the sync needs. Each engine has its own way to set up a narrower one, and on each the sync needs two places to write: the schema the tables live in, and a second one with _staging on the end, where a run holds changed rows before merging them.

Keep each user’s password in the environment variable with the rest of the connection string, never in the replication file.

Editions, replicas and maintenance

Cloud SQL comes in two editions, Enterprise and Enterprise Plus, and the difference that touches a sync is maintenance. Enterprise Plus is designed for near-zero downtime during planned maintenance, while an Enterprise instance restarts briefly in its window. Either way the sync recovers on its next run. Read replicas suit dashboards and agents, and read pools put several read nodes behind one address. Cloud SQL’s managed connection pooling is built for apps with many short connections, and the sync does not need it.

A list, as Cloud SQL sees it

Consider a training register on a site replicated with the prefix hr, with a Course lookup, a Trainee person column, a Score number and a multi-choice Certificates column. Replicate the Courses list too, and SPSync writes:

TableWhat it holds
hr_training_registerOne row per training record: sp_item_id, title, score, course_id, trainee_user_id, sp_created, sp_modified, sp_deleted_at
hr_coursesThe Courses list, joined on sp_item_id = course_id
hr_training_register__certificatessp_item_id, value, ordinal, a row per certificate earned
sp_usersThe people table every person column points at

PostgreSQL gets double precision for the score and timestamptz for dates, SQL Server gets float and datetime2, and MySQL gets DOUBLE, DATETIME(6) and a bounded VARCHAR for IDs. Schema changes in SharePoint carry through: new columns appear on the next run, removed ones stay in the table, and a retyped column gets a _v2 sibling.

Worked example: pass rates by course

select c.title as course,
count(*) as attempts,
avg(r.score) as average_score,
count(*) filter (where r.score >= 70) as passed
from hr_training_register r
join hr_courses c on c.sp_item_id = r.course_id
where r.sp_deleted_at is null
and r.sp_created >= now() - interval '90 days'
group by c.title
order by average_score;

That is PostgreSQL. On SQL Server, write the pass count as sum(case when r.score >= 70 then 1 else 0 end) and the date test as r.sp_created >= dateadd(day, -90, sysutcdatetime()); on MySQL, the same case expression and now() - interval 90 day. Looker can model the same join once and let HR filter by department or site.

When the first connection fails

After the first good run, check the result in Cloud SQL Studio or any client: select count(*) from hr.hr_training_register where sp_deleted_at is null should match the number of items in the list. The weekly reconcile, configurable per replication, makes the same comparison for every list and corrects any difference.

Querying the copy from BigQuery

If your analysts work in BigQuery, they do not need a second copy of the lists there. BigQuery’s federated queries reach Cloud SQL for PostgreSQL and MySQL through a connection resource, and run SQL on the instance:

select *
from external_query(
'my-project.europe-west2.hr-cloudsql',
'select c.title as course, count(*) as attempts
from hr.hr_training_register r
join hr.hr_courses c on c.sp_item_id = r.course_id
where r.sp_deleted_at is null
group by c.title');

The inner query runs on Cloud SQL, so put it on a read replica if the instance is busy. For warehouse-sized history, replicate the lists into BigQuery directly as a second destination.

On Cloud SQL for PostgreSQL the pgvector extension is available too. Enable it with create extension vector and choose the pgvector destination, and the sync adds an embedding to each row from the columns you name, calling OpenAI, Azure OpenAI or a local model during the run.

A Looker view over the register

Looker connects to Cloud SQL for PostgreSQL like any Postgres database. A view file for the training table needs little more than the table name and the key:

view: hr_training_register {
sql_table_name: hr.hr_training_register ;;
dimension: sp_item_id {
primary_key: yes
type: number
sql: ${TABLE}.sp_item_id ;;
}
dimension: score {
type: number
sql: ${TABLE}.score ;;
}
measure: average_score {
type: average
sql: ${score} ;;
}
}

Join it to a view on hr_courses through course_id, filter on sp_deleted_at being null, and HR has an explore that refreshes as the list changes.

Typical uses on Google Cloud

A Looker or Power BI report reads the tables directly. Cloud Run services use them as an application read replica. A Power Automate flow that copied list rows into a database can be switched off. Analysts join lists on the key columns.

Agents over the Cloud SQL copy

Give an AI agent a read replica and a database user that can only read the HR schema, then run a Postgres MCP server (or a SQL Server or MySQL one, to match the engine) against it, through its own Auth Proxy if that is how your network works. SPSync’s own read-only spsync mcp serve is the other option. Training records are personal data, and SharePoint’s item permissions do not come across with them, so the database user’s grants and a row-level security policy are how you keep one manager’s agent to their own team’s records.

Cloud SQL limits worth knowing

Set-up order

  1. Decide the connection route above and test it from the sync host with the engine’s own client.
  2. Sign in to SharePoint with delegated access, or have an admin grant Sites.Selected on the sites the sync needs.
  3. Put the connection string in an environment variable and name it in the destination settings.
  4. Choose the lists, libraries or whole site and run. The first run loads everything; later runs read changes, with a reconcile, weekly by default.

Google bills Cloud SQL for the instance, its storage and any public IP, 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

Which Cloud SQL engines can SPSync write to?

Cloud SQL for PostgreSQL, for MySQL and for SQL Server. The sync behaves on each as it does on that engine anywhere else.

Do I need the Cloud SQL Auth Proxy?

It is the simplest route. Run the proxy next to SPSync and connect to localhost with no TLS settings, because the proxy encrypts the connection. A direct connection also works over a private IP, or a public IP listed in authorised networks, with the TLS settings the instance's SSL mode asks for.

Can SPSync use IAM database authentication on Cloud SQL?

No. SPSync sends a database username and password. When you use the Auth Proxy, IAM authorises the proxy to reach the instance, which is a separate step from the database login.

What happens to the sync during a Cloud SQL maintenance window?

Maintenance restarts the instance briefly. A run that overlaps it fails to connect or is cut off, and the next scheduled run reads every change since the last run that completed, so nothing is skipped.

Talk to us about Google Cloud SQL (SQL Server, Postgres, MySQL)

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 PostgreSQL setup guide, MySQL and MariaDB setup guide or SQL Server setup guide to create the database user and open the connection for Google Cloud SQL (SQL Server, Postgres, MySQL). 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 google_cloud_sql --prefix google_cloud_sql --destination-kind postgres --connection-string-env SPSYNC_DB_CONNECTION --dataset-name google_cloud_sql --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: google_cloud_sql
prefix: google_cloud_sql
auth:
  mode: delegated
  client_id: 00000000-0000-0000-0000-000000000000
  tenant_id: common
destination:
  kind: postgres
  connection_string_env: SPSYNC_DB_CONNECTION
  dataset_name: google_cloud_sql
scopes:
  - site_url: https://contoso.sharepoint.com/sites/example
    mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false

Cron (PostgreSQL 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

Book a call to talk through your use case, see further walkthroughs or demos, and set up a trial in your own environment.