SharePoint to Azure Database for MySQL

Azure Database for MySQL Flexible Server as a home for SharePoint lists, over TLS, for Azure-hosted apps, Metabase or Power BI.

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 Azure Database for MySQL.

Status: Shipped · product: SPSync for Relational Databases

Azure Database for MySQL Flexible Server turns TLS on for new servers, and getting that one setting right is most of the work. After that, SPSync writes SharePoint lists as MySQL tables that an App Service app, a Function, Metabase or Power BI’s MySQL connector reads as it would any other database.

TLS, sign-in and the network path

Download the root certificate Microsoft publishes for Flexible Server, DigiCert Global Root G2 at the time of writing, and add ssl_ca=/path/to/the-certificate.pem to the connection string. The MySQL driver SPSync uses treats that as “require TLS and verify the server”. Do not also add ssl_verify_identity=true; with this driver it discards the certificate path and turns verification off.

Sign-in is a MySQL username and password, read from the environment variable that holds the connection string. Flexible Server accepts a plain username. Older Single Server instances often expect user@servername. Microsoft Entra authentication is not supported today.

Open one network path before the first run:

Test it from wherever the sync will run, whether that is a desktop, SPSync in your Azure or a build agent, because an admin’s own laptop often has a path the sync host lacks.

Tables and types

An approved-vendor list with a Category lookup, a Buyer person column and a multi-choice Regions column becomes proc_vendors, keyed on the SharePoint item ID, with category_id and category_value, a buyer_user_id that joins to sp_users, and a proc_vendors__regions child table. GUIDs and shorter text columns are bounded VARCHAR(n), so you can put a unique index on them. Long text stays TEXT and is not indexed for you. Table and column names are capped at 64 characters, and SPSync shortens longer SharePoint names to fit.

A new SharePoint column appears on the next run, a removed one stays, and a retyped column gets a _v2 column alongside.

Uses on Azure

An app’s read model. An App Service or Function that reads reference data through Graph can query the server instead; see a read replica for internal apps.

Dashboards. Metabase or Grafana connect with their MySQL drivers; see Tableau, Looker, Metabase and Grafana on SharePoint data.

Master data for integrations. Cost centres and product codes become tables Logic Apps can query; see reference and master data from SharePoint.

A move off SharePoint lists. The replica gives an application something to cut over to; see migrating list data off SharePoint.

Steps

  1. Start with delegated sign-in, or ask a SharePoint admin to approve Sites.Selected on the sites so the sync can run unattended.
  2. Create a MySQL user that can create tables in the target database.
  3. Store the connection string, with ssl_ca, in an environment variable.
  4. Choose lists or a whole site and run; the first run creates the schema.
  5. Set a schedule. Later runs read changes only, with a reconcile, weekly by default.

The server’s compute tier affects how long the first full load of a large list takes far more than it affects later runs.

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

Is this the same as the MySQL destination?

Yes, it is the MySQL destination pointed at Microsoft's managed service. This page covers the Azure parts: TLS, sign-in and networking.

How does SPSync authenticate to Azure Database for MySQL?

With a MySQL username and password over TLS. Microsoft Entra authentication is not supported today.

Which certificate setting does the connection string need?

Only ssl_ca, set to the path of the root certificate Azure publishes for Flexible Server. That one setting makes TLS required and verifies the server. Adding ssl_verify_identity as well switches verification off in the MySQL driver SPSync uses, so leave it out.

Can several SharePoint sites replicate into one server?

Yes. Each site's tables get their own prefix, so several sites share a database without name clashes.

Talk to us about Azure Database for 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 MySQL and MariaDB setup guide to create the database user and open the connection for Azure Database for 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 azure_database_for_mysql --prefix azure_database_for_mysql --destination-kind mysql --connection-string-env SPSYNC_DB_CONNECTION --dataset-name azure_database_for_mysql --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: azure_database_for_mysql
prefix: azure_database_for_mysql
auth:
  mode: delegated
  client_id: 00000000-0000-0000-0000-000000000000
  tenant_id: common
destination:
  kind: mysql
  connection_string_env: SPSYNC_DB_CONNECTION
  dataset_name: azure_database_for_mysql
scopes:
  - site_url: https://contoso.sharepoint.com/sites/example
    mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false

Cron (MySQL 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.