A self-hosted music-streaming server's database for a multi-user library where each person owns their own catalog. One songs table holds both tracks and podcast episodes, so most "playable" relations point back at it.
What this Koel schema covers
Artists, albums, songs, genres, and folders
Standard and smart playlists, sharing, and collaborators
Podcast feeds, subscriptions, and listening state
Play counts, favorites, ratings, and embeds
Spatie roles/permissions and an audit trail
A few decisions the diagram can't show:
Three ID strategies coexist: ULID char(26) for catalog rows, varchar(36) for songs and playlists, auto-increment for pivots. That mix is why every polymorphic *_id is a string.
favorites, ratings, and embeds are polymorphic, so one row can target a song, album, artist, or podcast.
Play tracking is isolated in interactions, separate from favorites and ratings.
A playlist is "smart" only when playlists.rules holds a JSON filter; empty rules means a hand-curated list.
songs.storage records which storage driver a file lives on; artist_name/album_name are denormalized onto songs.
Good fork target for a single-tenant or org-scoped media server. Note songs doubles as the podcast-episode table, so it is wider than a pure music catalog.
Self-hosted personal music streaming server — Koel is a self-hosted, open-source music streaming server built with Laravel and Vue. It serves music you own through a private, Spotify-style web player.