# How Music Assistant Synchronizes Your Library Across Multiple Music Providers

> Learn how Music Assistant synchronizes your library across Spotify YouTube Music local files and more preventing data loss for a unified music experience.

- Repository: [Music Assistant/server](https://github.com/music-assistant/server)
- Tags: deep-dive
- Published: 2026-06-21

---

**Music Assistant aggregates content from Spotify, YouTube Music, local files, and other sources into a unified library by running a provider-agnostic synchronization routine that reconciles external catalogs with a local SQLite database while preventing data loss when the same media exists across multiple providers.**

Music Assistant is an open-source music server designed to consolidate your entire music collection into a single interface. The `music-assistant/server` repository implements a robust synchronization architecture that enables seamless Music Assistant library sync across multiple providers without duplicating entries or losing user favorites. This system allows users to browse artists, albums, and tracks regardless of whether they originate from streaming services or local storage.

## Architecture Overview

The synchronization system operates through four distinct layers, each with specific responsibilities defined in the source code.

**Provider Base Class** – Located in [`music_assistant/models/music_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/music_provider.py), this layer defines the public `sync_library` method and internal helpers such as `_sync_library_artists`, `_sync_library_albums`, and `_sync_library_tracks`. These methods handle the actual database operations at lines 690 through 711.

**Concrete Providers** – Individual services like Spotify ([`music_assistant/providers/spotify/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/spotify/provider.py)) and WebDAV ([`music_assistant/providers/webdav/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/webdav/provider.py)) implement media-specific generators such as `get_library_tracks` and `get_library_artists` that yield provider-native IDs and metadata.

**Sync Controller** – The orchestration layer in [`music_assistant/controllers/music/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/music/controller.py) (line 2334) initiates sync requests by calling `await provider.sync_library(media_type)` for specific media types.

**Database Layer** – All library items persist in `$HOME/.musicassistant/library.db`, where each row stores the provider ID, media type, and a JSON-encoded `sources` array tracking which providers claim each item.

## How the Sync Process Works

The library synchronization follows a strict reconciliation pattern that ensures data consistency across multiple music providers.

### Entry Point and Media Type Dispatch

When a sync initiates, the system calls `MusicProvider.sync_library(media_type)` defined at line 690 of [`music_assistant/models/music_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/music_provider.py). This method branches to type-specific internal helpers:

```python
if media_type == MediaType.ARTIST:
    cur_db_ids = await self._sync_library_artists()
elif media_type == MediaType.ALBUM:
    cur_db_ids = await self._sync_library_albums()

# … extends to TRACK, PLAYLIST, PODCAST, RADIO, AUDIOBOOK

```

Each helper (lines 699-711) operates as an async generator consumer, pulling the current state from the provider's API and comparing it against existing database records.

### Database Reconciliation and Updates

The internal helpers retrieve the current set of IDs from the provider and return the **set of database row IDs** that correspond to active items. For tracks, this occurs in `_sync_library_tracks` (referenced around line 1159).

The system performs three critical operations:

- **Insertion** – New items present on the provider but absent from the database are added via the `library_add` method.
- **Metadata refresh** – Existing entries receive updated metadata regardless of deletion settings, ensuring the UI displays current information.
- **Source tracking** – The `sources` JSON field tracks every provider claiming the item, enabling the unified library view.

### Safe Deletion Logic

When an item disappears from a provider, the sync routine checks whether other providers still claim it before removing the favorite status or deleting the entry. This safety mechanism prevents accidental loss of library items that exist across multiple providers.

The behavior is verified in [`tests/test_library_sync.py`](https://github.com/music-assistant/server/blob/main/tests/test_library_sync.py), which confirms that:

- Items are unmarked as favorites only when no other providers reference them.
- Items persist in the library if at least one alternative provider still offers them.

## Provider Implementation Requirements

To participate in library synchronization, a provider must implement async generators for each supported media type. The Spotify provider demonstrates this pattern:

```python
async def get_library_tracks(self) -> AsyncGenerator[Track]:
    async for track_data in self.api.list_saved_tracks():
        yield Track(
            item_id=track_data["id"],
            name=track_data["name"],
            # …additional metadata fields

        )

```

The base class automatically consumes these generators during `sync_library` execution, requiring no additional synchronization code unless the provider needs custom rate-limiting or pagination handling.

## Practical Usage Examples

### Triggering Provider-Specific Syncs

You can manually synchronize specific media types for any configured provider:

```python
await mass.providers.spotify.sync_library(MediaType.TRACK)
await mass.providers.spotify.sync_library(MediaType.ALBUM)
await mass.providers.spotify.sync_library(MediaType.PLAYLIST)

```

These calls execute the generic `sync_library` method, which handles the reconciliation logic automatically.

### Home Assistant Service Calls

Force a sync using the Home Assistant integration:

```yaml
service: music_assistant.sync_library
data:
  provider: spotify
  media_type: track

```

### Inspecting the Unified Database

View how Music Assistant merges entries from multiple sources:

```bash
sqlite3 ~/.musicassistant/library.db "SELECT provider, item_id, sources FROM library_items WHERE media_type='track';"

```

The `sources` column displays a JSON array listing every provider that reported each track, demonstrating the multi-provider consolidation in action.

## Summary

- **Music Assistant library sync** operates through a centralized `sync_library` method in [`music_assistant/models/music_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/music_provider.py) that works uniformly across all provider types.
- **Provider implementations** only need to supply async generators like `get_library_tracks`, while the base class handles database reconciliation and conflict resolution.
- **Deletion safety** ensures that removing a provider or losing access does not delete library items that exist on other connected services.
- **Metadata caching** keeps the local database refreshed with current information from all sources, enabling fast UI rendering and consistent search results.

## Frequently Asked Questions

### How does Music Assistant prevent duplicate entries when syncing the same album from Spotify and local files?

Music Assistant tracks every provider claiming an item in the `sources` JSON field of the database. When the same album appears in both Spotify and local storage, the sync routine recognizes it as a single library entry with multiple sources, displaying it once in the UI while maintaining links to both playback locations.

### Can I force a library sync for all providers simultaneously?

While the controller typically manages sync scheduling, you can trigger individual provider synchronization using the Home Assistant service `music_assistant.sync_library` or programmatically calling `sync_library()` for each media type on each provider instance. There is no single "sync all" command; each provider handles its own media types independently.

### What happens to my favorites if I disconnect a music provider?

Favorites remain intact as long as the item exists on at least one other connected provider. The deletion logic in [`music_assistant/models/music_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/music_provider.py) checks the `sources` array before removing favorite status. Only when no providers claim an item does the system mark it as removed or delete the entry entirely.

### Where does Music Assistant store the synchronized library data?

The unified library persists in `$HOME/.musicassistant/library.db` as a SQLite database. This file contains metadata, provider mappings, and source tracking information, while the actual audio files remain on their respective provider systems or local storage paths.