Music Streaming ER diagram and database schema
The Music Streaming database schema is a DB Planner template with 26 tables, 177 columns and 40 relationships, free to use. Core tables include artists, audio_files, availability_windows, devices. It can be opened as an interactive ER diagram or exported as PostgreSQL, MySQL, or SQL Server DDL.
- Tables
- 26
- Columns
- 177
- Relationships
- 40
- Category
- Social
- Exports
- DBML, SQL, C#
- Price
- Free
What this schema models
A complete music streaming app database design, modeled on how streaming services actually separate catalog, rights and listening: 26 tables, 11 enums and 40 relationships covering artists, releases, tracks, credits and genres, labels, territory availability windows and audio encodings, users, plans, per-country prices and family subscriptions, playlists, collaborators, follows and saved library items, devices and the play event stream, and daily play counts feeding pro-rata royalty pools and statements. THE FOUR DESIGN RULES 1. A RELEASE is not a TRACK. A track is a recording with an ISRC; a release (album, single, EP or compilation) has a UPC and a tracklist with disc and position. The same song on the single and on the album is one track, with one play count and one royalty line. 2. Credits are rows with roles. Many artists link to a track as main, featured, producer, writer, composer or remixer, in display order. "A feat. B" is rendered from those rows, never stored as a string, so the featured artist page finds the track too. 3. Play events are an append-only firehose; reports read rollups. play_events is partitioned monthly by played_at, never updated, and copies the territory and plan tier at play time. A daily job rolls it up into play_counts per track, territory and tier, which charts, artist dashboards and royalty runs read instead. 4. Royalties are pooled, then split by share of streams. Each month the net revenue of a territory and tier forms a pool; the per-stream rate is revenue times the rights share divided by qualified streams (30 seconds or more), and each label statement is its qualified streams times that rate. DETAILS WORTH STEALING - Playlists order tracks by a lexicographic rank, so dragging track 900 to the top of a 1,000-track playlist rewrites one row; entries have their own id because a track can appear twice. - Follows and library saves use one nullable foreign key per target plus a check constraint, so every follow is an enforced foreign key instead of a generic target_id. - Availability windows are per release, territory and access tier, and a takedown ends a window instead of deleting the release, so play history survives. - Audio files are one row per encoding, with codec, bitrate, loudness for volume normalization and a preview flag; a CDN serves the bytes. - Duo and family plans have members, with a partial unique index allowing one current plan per user; prices are per country and versioned, and a subscription keeps the price it was sold at. - unique_listeners in the daily rollup is flagged as not summable across days, a classic bug in monthly listener reports. WHAT YOU GET Clean DBML that imports directly into DB Planner, and a laid-out board with zones color-coded and framed: listening, users and subscriptions, library and social, catalog, rights and media, and play counts and royalties. Every table carries a note. Postgres-flavoured types that port cleanly to MySQL or SQL Server. Useful for developers building a music or audio streaming app, and for students who need a realistic music streaming ER diagram for a DBMS project. This is a schema design reference; real royalty deals, publishing rights and licensing terms vary widely and belong in your own business logic.
Tables (26)
| Table | Columns |
|---|---|
| artists | 10 |
| audio_files | 10 |
| availability_windows | 6 |
| devices | 6 |
| follows | 6 |
| genres | 3 |
| labels | 5 |
| library_saves | 5 |
| plan_prices | 7 |
| play_counts | 7 |
| play_events | 12 |
| playlist_collaborators | 3 |
| playlist_tracks | 6 |
| playlists | 10 |
| release_artists | 3 |
| release_tracks | 4 |
| releases | 12 |
| royalty_pools | 10 |
| royalty_statements | 9 |
| subscription_members | 4 |
| subscription_plans | 7 |
| subscriptions | 10 |
| track_credits | 4 |
| track_genres | 2 |
| tracks | 8 |
| users | 8 |
Relationships (40)
audio_files.track_id references tracks.idmany to oneavailability_windows.release_id references releases.idmany to onedevices.user_id references users.idmany to onefollows.followed_artist_id references artists.idmany to onefollows.followed_playlist_id references playlists.idmany to onefollows.followed_user_id references users.idmany to onefollows.follower_id references users.idmany to onegenres.parent_id references genres.idmany to onelabels.parent_label_id references labels.idmany to onelibrary_saves.release_id references releases.idmany to onelibrary_saves.track_id references tracks.idmany to onelibrary_saves.user_id references users.idmany to oneplan_prices.subscription_plan_id references subscription_plans.idmany to oneplay_counts.track_id references tracks.idmany to oneplay_events.device_id references devices.idmany to oneplay_events.track_id references tracks.idmany to oneplay_events.user_id references users.idmany to oneplaylist_collaborators.playlist_id references playlists.idmany to oneplaylist_collaborators.user_id references users.idmany to oneplaylist_tracks.added_by references users.idmany to oneplaylist_tracks.playlist_id references playlists.idmany to oneplaylist_tracks.track_id references tracks.idmany to oneplaylists.owner_user_id references users.idmany to onerelease_artists.artist_id references artists.idmany to onerelease_artists.release_id references releases.idmany to onerelease_tracks.release_id references releases.idmany to onerelease_tracks.track_id references tracks.idmany to onereleases.label_id references labels.idmany to oneroyalty_statements.label_id references labels.idmany to oneroyalty_statements.royalty_pool_id references royalty_pools.idmany to onesubscription_members.subscription_id references subscriptions.idmany to onesubscription_members.user_id references users.idmany to onesubscriptions.owner_user_id references users.idmany to onesubscriptions.plan_price_id references plan_prices.idmany to onesubscriptions.subscription_plan_id references subscription_plans.idmany to onetrack_credits.artist_id references artists.idmany to onetrack_credits.track_id references tracks.idmany to onetrack_genres.genre_id references genres.idmany to onetrack_genres.track_id references tracks.idmany to onetracks.label_id references labels.idmany to one
How to use this template
- Open the ER diagram to see the tables and how they relate.
- Copy it into your workspace. You get your own editable copy, in DBML.
- Export it as PostgreSQL, MySQL, or SQL Server DDL, or as C# models.
The copy opens in DB Planner’s ER diagram tool, with the schema as text in the DBML editor beside it. Have a database already? Turn its SQL into an ER diagram instead.
Frequently asked questions
- What is in the Music Streaming database schema?
- 26 tables and 40 relationships, across 177 columns. The table names and the full relationship list are shown on this page.
- Can I export it to PostgreSQL or MySQL?
- Yes. Every DB Planner template exports as DBML, as PostgreSQL, MySQL, or SQL Server DDL, and as C# models.
- Is this template free?
- Yes. You can open it in the browser without an account, and copy it into your own workspace with a free DB Planner account.
- Can I change it after copying it?
- Yes. A copy is yours: you can rename tables, add columns, and export it. Changes the author makes later do not affect your copy.