Databases and apps on SharePoint data

Building an application read replica or a document catalogue in Postgres, Supabase or another database, with a normalised schema an app can query directly.

A team keeps its supplier records in a SharePoint list and has been asked for a small web app over the same data. The first version calls Microsoft Graph directly. It works in testing, then starts backing off from throttling responses once real users arrive, and every column has to be translated from SharePoint's field types before the app can use it.

What the app wants is a database. With a replica in PostgreSQL, Supabase, MySQL, MariaDB or SQLite, it reads tables with typed columns and whatever indexes you add. A lookup becomes a key column you can join on, a multi-value column becomes a child table keyed on sp_item_id, and people sit in one shared sp_users table. The app, or an API in front of it, queries that copy as it would any other database, with no SharePoint code in it at all.

People keep editing in SharePoint. The replica catches up on a schedule, every five minutes by default, by reading only the items that changed since the last run, so the app never calls Graph and never competes with other integrations for the tenant's throttling budget. When someone adds a column to the list, the column appears in the table on the next run. A removed column stays, so nothing the app reads disappears, and on PostgreSQL, MySQL, MariaDB and SQLite a column whose type changes gets a _v2 column beside the old one.

The replica only goes one way. SPSync reads from SharePoint and writes to the database, and nothing flows back. An app that needs to change a SharePoint item keeps doing that through its own Graph call, or keeps its own data in its own tables. Write-back is designed on the two-way sync roadmap page and has not shipped. SharePoint item permissions are not copied either, so who can read which rows comes down to the database roles and row-level security you grant.

Each post here takes one destination and one team, from a Supabase client portal to an offline SQLite file a caseworker carries on a laptop. They share one schema, so what you learn on one destination carries over to the next.

Start here

  1. SharePoint lists in PostgreSQL, ready for Metabase and apps

    PostgreSQL comes first because it shows the table shape every other destination in this topic shares.

  2. A client portal on Supabase, fed from SharePoint lists

    Supabase puts an app on those same tables, with its table editor, REST API and Realtime.

  3. An offline SQLite copy of SharePoint lists for caseworkers

    The SQLite post is for a copy that has to work offline, in one file on a laptop.

  4. SharePoint to MySQL or MariaDB for a Grafana defects board

    MySQL and MariaDB come last, for teams that already run one of them and chart it in Grafana.

All posts on this topic

Other topics on the blog

Frequently asked questions

Why not just call the Graph API from the application directly?

It works for low-volume, occasional reads. It gets fragile once an application depends on it continuously: Graph throttling responses need handling, lookup and person columns need resolving on every call, and any schema change on the list can change the shape of what the API returns without warning.

Does the application ever write back through SPSync?

SPSync only reads from SharePoint and writes to the destination database. An application that needs to write to SharePoint keeps doing so through its own Graph calls.

How does this handle a list's schema changing over time?

New columns are added automatically and removed columns stay, so no data is dropped. On SQL Server, PostgreSQL, MySQL, ClickHouse, Oracle, SQLite and DuckDB, a retyped column gets a versioned column beside the old one, so an application reading the table keeps working through an unexpected change. Other destinations do not fork a retyped column this way today.