Last updated
One way: SharePoint stays the system of record, and SPSync keeps a read-only copy of your lists current in Elasticsearch.
Status: Shipped · product: SPSync for Search & Vector Stores
SPSync sends SharePoint list items one way into Elasticsearch indexes with explicit
mappings, for keyword and filtered search, and writes no dense_vector field. Vector or
hybrid search over these documents needs an embedding job of your own that reads the
text, embeds it and keeps the vectors in an index you manage. Embeddings on sync for
Elasticsearch are an idea under consideration, with no plan or date; SPSync writes them
today only to Postgres with pgvector and
Azure AI Search.
If your organisation already runs the Elastic stack, SharePoint lists become one more set of indexes on the cluster, searchable with the same query DSL and explorable in Kibana next to whatever else you index.
Connecting to the cluster
Give SPSync the cluster URL, for example https://my-cluster.example.com:9200 on your own
servers or the endpoint Elastic Cloud shows, and one of two credentials held in
environment variables:
- an Elasticsearch API key, or
- a username and password for HTTP basic auth.
SPSync keeps a local state file on the sync host to track what it has sent, so give that file a stable path.
One index per table
Every SPSync table becomes an index: one per list, one per multi-value column, and one
shared sp_users index for people. A service catalogue list, it_services, gives an
it_services index plus it_services__platforms for a multi-choice Platforms column.
Documents carry a lookup’s ID and display value, and a person column’s user ID, which
joins to the sp_users index for names and email.
The mapping is explicit. IDs are keyword, matched as whole values and never analysed. Text,
choice values and lookup display values are analysed text, good for relevance search.
Numbers, dates and Yes/No fields keep their types, so range filters and aggregations work
on them. Elasticsearch cannot change a field’s type in place, so when a SharePoint column
changes type SPSync creates a new {index}_v2 index with the fresh mapping and writes
there from then on.
What each run sends
Only documents whose content changed since the last successful push are sent, plus deletions. A reconcile, weekly by default, re-sends everything, which repairs documents changed or removed in the cluster by hand. A failed push is retried on the next run.
How it gets used
A dedicated search page over SharePoint lists, keyword retrieval for chat over your SharePoint data, and a search tool for AI agents. Pipelines that need vector or hybrid retrieval use pgvector or Azure AI Search instead; see RAG on SharePoint lists.
Steps
- Connect to SharePoint with delegated sign-in, or with an app that an admin has granted
Sites.Selectedon the sites to index. - Create an API key, or a user, that can create indexes and write documents.
- Set the cluster URL and the credential variables.
- Choose the lists and run; the first run creates the indexes and loads every item.
- Point your search UI or Kibana at the indexes.
Shard counts and mapping choices affect cluster cost as lists grow. SharePoint permissions are not carried into the index, so cluster and index access is the boundary; scope read access accordingly.
Watch it run
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 an empty Elasticsearch cluster, and the replicated indices searched in Kibana.
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
Why replicate to Elasticsearch instead of using SharePoint search?
SharePoint search offers little control over relevance or exact filters on list columns. An Elasticsearch index over the lists you choose gives you the query DSL, relevance tuning and aggregations, refreshed on your schedule.
Does SPSync set the index mappings, or let Elasticsearch guess?
SPSync sets them. Each index gets an explicit mapping built from the list's columns, and a new column is added with its own mapped type, never Elasticsearch's dynamic guess, which often gets IDs wrong.
Can Elasticsearch do vector search on this data?
No. SPSync's Elasticsearch destination is keyword and filtered search only today, with no dense vector field. For vector or hybrid search, see SharePoint to pgvector or SharePoint to Azure AI Search.
What happens to a document when the SharePoint item is deleted?
SPSync deletes the document on the next run, together with that item's documents in the child indexes, so a search never returns something that no longer exists.
Will SPSync connect to an OpenSearch cluster?
No. The Elasticsearch client SPSync uses refuses to talk to OpenSearch. Use the OpenSearch destination for Amazon OpenSearch Service or a self-hosted OpenSearch cluster.
Talk to us about Elasticsearch
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 Elasticsearch setup guide to create the database user and open the connection for Elasticsearch. 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 elasticsearch --prefix elasticsearch --destination-kind elasticsearch --connection-string-env SPSYNC_DB_CONNECTION --dataset-name elasticsearch --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: elasticsearch
prefix: elasticsearch
auth:
mode: delegated
client_id: 00000000-0000-0000-0000-000000000000
tenant_id: common
destination:
kind: elasticsearch
connection_string_env: SPSYNC_DB_CONNECTION
dataset_name: elasticsearch
scopes:
- site_url: https://contoso.sharepoint.com/sites/example
mode: entire_site
reconcile_interval_days: 7
create_reporting_views: false
Cron (Elasticsearch 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.