SharePoint to SQLite (local file, desktop analytics)

One SQLite file per replication, no server to run: SharePoint lists for desktop analysis, scripts, offline queries and quick evaluation.

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 SQLite.

Status: Shipped · product: Included in every product

The simplest place to put a SharePoint list is a file. SQLite runs without a server and needs neither a connection string nor credentials of its own: SPSync writes one file at a path you choose, and you open it with DB Browser for SQLite, DuckDB, pandas or any language’s SQLite driver.

What the file holds

A course booking list with a Course lookup, an Attendee person column, a Booked on date and a multi-choice Dietary needs column becomes a train_bookings table keyed on the SharePoint item ID. course_id and course_value carry the lookup. attendee_user_id lines up with the shared sp_users table. train_bookings__dietary_needs has one row per booking and need, so a query joins it with plain SQL and never splits a delimited string.

Deleted items keep their row with sp_deleted_at set. New SharePoint columns appear on the next run, removed ones stay in the file, and a retyped column keeps its history while a _v2 column takes the new type.

Three SQLite habits to know

SQLite declares types without enforcing them, and two of SPSync’s choices follow from that.

Ways people use the file

Behind a small tool or script. A notebook or local utility that called Graph for reference data reads the file instead, with no network round trip; see a read replica for internal apps.

Desktop analysis. An analyst gets a relational schema in DB Browser for SQLite, R or Python, and stops exporting CSVs by hand; see reporting and analytics on SharePoint list data.

A queryable backup. Because deleted items stay on record, a copy of the file is a point-in-time backup of the list; see continuous backup and history of lists.

Evaluation. SQLite needs no decisions up front, so it shows the schema SPSync generates before you choose Postgres, SQL Server or a warehouse.

Setting it up

  1. Sign in with delegated access. A scheduled sync on a server needs Sites.Selected app permissions, which an admin approves per site.
  2. Choose a path for the file. SPSync creates it on the first run.
  3. Choose the lists or a whole site. The first run creates one table per list, child tables for multi-value columns and sp_users.
  4. Set how often it runs, every few minutes up to hourly.
  5. Open the file in the tool you prefer.

The file needs to sit where its readers can open it, so most SQLite syncs run from the desktop app on the machine that uses the file, or from the command line as a build step that regenerates it.

Watch it run

Watch the full video

Chapters are in the video's description.

Watch the walkthrough: the Northwind Analytics demo lists in SharePoint, connecting to Microsoft 365 in the desktop app, picking lists, the run into a local SQLite file, and the replicated tables and rows.

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

Do I need a database server to use SQLite as a destination?

No. SPSync writes one SQLite file on disk, so there is nothing to install or run apart from SPSync, which makes it the quickest way to see first rows.

Can I query the file while a sync is writing to it?

Yes. SPSync opens the file in WAL mode, so a reader such as DB Browser for SQLite, DuckDB or a script is not blocked while the next run writes.

How large a list can one SQLite file hold?

SPSync is tested to 10,000 items on a live tenant and to 1,000,000 on a synthetic Graph, and SQLite copes well with large single files. For many users writing or reading at once, a server database such as Postgres or SQL Server is the better choice.

Is there a free trial for the SQLite destination?

SQLite is included in every SPSync product, so there is no separate trial to start. Get in touch if you would like a walkthrough first.

Does SPSync create foreign key constraints?

No. Each table gets a primary key, and every lookup or person column gets a key column to join on, such as client_id or owner_user_id. No constraint ties those columns together, so rows can arrive in any order without failing a run. Once the schema has settled you can add constraints yourself.

Talk to us about SQLite (local file, desktop analytics)

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 SQLite setup guide to create the database user and open the connection for SQLite (local file, desktop analytics). 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 sqlite --prefix sqlite --destination-kind sqlite --connection-string-env SPSYNC_DB_CONNECTION --dataset-name sqlite --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: sqlite
prefix: sqlite
auth:
  mode: delegated
  client_id: 00000000-0000-0000-0000-000000000000
  tenant_id: common
destination:
  kind: sqlite
  connection_string_env: SPSYNC_DB_CONNECTION
  dataset_name: sqlite
scopes:
  - site_url: https://contoso.sharepoint.com/sites/example
    mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false

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