System Design Problem

Design a Music Streaming Service (Spotify)

Commonly Asked By:SpotifyAppleAmazonNetflix

Interview Setup

Interview Prompt

Design Spotify for on-demand music streaming with search, playlists, offline downloads, and cross-device playback supporting 200M DAU and 50M concurrent listeners.

Clarifying Questions (ask before designing)

QuestionWhy it matters
How do we deliver audio between pre-encoded bitrates via CDN and adaptive streaming like HLS?At 12.8 Tbps peak (50M listeners streaming 256 kbps generating 10M chunk requests per second at 5-second intervals), pre-encoded files with HTTP range requests are simpler than live transcoding. Adaptive bitrate manifests matter primarily for heavy video streams.
Where do playlists reside and how do collaborative edits handle conflicts?When 200M DAU create playlists, write patterns scale rapidly. Cassandra handles high-cardinality playlist rows while optimistic locking with version counters and anchored position gaps handle collaborative playlists.
How does offline synchronization function between full downloads and progressive caching?Offline mode pre-downloads encoded files to device storage. At 5 MB per song, a 50-song playlist requires 250 MB, which demands resumable downloads and DRM token expiry handling.
How does the system track playback for royalty payments?Serving 2B streams per day (approximately 23K streams per second) feeds a financial royalty ledger. Client-side durable buffering and asynchronous Kafka ingestion avoid lost royalty events without putting ledger writes on the critical playback path.

Scope

In scope

  • Audio streaming protocols and chunk delivery
  • Playlist management, versioning, and collaborative editing
  • Offline synchronization and DRM token caching
  • Audio codec selection and bitrate tiers
  • CDN delivery architecture and origin shielding
  • Capacity estimation with explicit math

Out of scope (state explicitly)

Functional Requirements

Start by asking your interviewer about catalog browsing, on-demand playback, playlist management, and offline download scope. Recommendations and royalty tracking serve as common architectural follow-ups.

  • Stream music: Play songs on demand with continuous gapless playback.
  • Search: Search across tracks, artists, albums, genres, and lyrics.
  • Playlists: Create, edit, share, and follow personal, editorial, and algorithmic playlists.
  • Library: Save songs, albums, and artists to a user's personal library.
  • Recommendations: Deliver personalized recommendations such as Discover Weekly, Daily Mix, and Release Radar.
  • Social: Follow friends, monitor live listening activities, and contribute to collaborative playlists.
  • Offline mode: Download encrypted songs for playback without network connectivity.
  • Podcasts: Stream and download audio podcast episodes.
  • Queue management: Control playback queues with smart dithered shuffle and repeat.
  • Cross-device playback: Seamlessly transfer playback between active devices using Spotify Connect.

Scope alignment: Podcasts and social listening share underlying audio delivery primitives (HTTP range streaming, CDN edge caching, and Kafka event ingestion). Specialized podcast features (such as RSS polling and dynamic server-side ad stitching) and real-time friend activity feeds reuse these shared platform primitives while their dedicated domain internals are explored in focused companion designs.

Non-Functional Requirements

Your interviewer will care most about playback startup latency and gapless streaming continuity. CDN placement for audio chunks follows directly from serving a global user base.

  • Low latency startup: Achieve time-to-first-playable-audio under 200 ms on normal networks by decoding initial audio frames immediately, while concurrently buffering ahead using 5-second range requests to maintain a steady-state buffer.
  • High availability: 99.99% uptime for core audio streaming and catalog discovery paths.
  • Scalability: Scale to 500M registered users, 200M DAU, and 100M catalog tracks.
  • Smooth playback: Eliminate buffering interruptions under standard network conditions through adaptive prefetching.
  • Content protection: Enforce digital rights management (DRM) to prevent unauthorized stream ripping and file extraction.
  • Global distribution: Deliver low-latency audio worldwide through geo-distributed CDN edge locations.
  • Personalization freshness: Update recommendation feeds and discovery playlists on weekly and daily cadences.

Capacity Estimations

Run this math before sizing the CDN infrastructure. Catalog size, concurrent listener volume, and target audio bitrates establish egress bandwidth and metadata storage requirements.

MetricCalculationValue
Total usersGiven (product assumption)500M
DAUGiven (product assumption)200M
Total songsGiven (assumption documented in value)100M
Avg song size (reference)Typical duration (~160s) @ 256 Kbps reference~5 MB
Single-tier catalog storage100M songs x ~5 MB reference500 TB
Multi-variant catalog storage (4 tiers)500 TB x (600 Kbps ÷ 256 Kbps) ≈ 2.34x~1.17 PB (planning estimate before overhead)
Concurrent listenersGiven (peak load assumption)50M
Aggregate streaming bandwidth50M x 256 Kbps reference12.8 Tbps
CDN edge chunk request rate50M listeners ÷ 5-second chunk duration~10M req/sec
Origin request rate (10% edge miss)10M req/sec x 10% miss rate~1M req/sec (shielded)
Songs played / day200M DAU x 10 songs/day2B (10 per user)
Baseline stream rate (ingestion)2B ÷ 86,400 seconds~23K streams/sec baseline

Architecture Diagram

In the room: separate discovery and browse queries from audio playback delivery early in the interview.

Walk your interviewer through the architecture by separation of concerns. We decouple catalog metadata from audio streaming delivery because they exhibit fundamentally different caching profiles. Song metadata and playlists reside in relational and NoSQL stores with dedicated search indexing, whereas audio files are stored in object storage and streamed through CDN edge PoPs using HTTP range requests. Listening history feeds an offline batch recommendation pipeline, while playback events stream asynchronously into Apache Kafka for royalty calculation.

Loading...

Component Deep Dives

We examine each building block across the architecture, covering audio delivery first, followed by catalog storage, session registries, and asynchronous processing pipelines.

Audio Streaming Architecture

Audio playback is CDN-backed with chunked HTTP range requests so that application API servers remain completely decoupled from the audio byte transfer path.

  1. The client requests song metadata from the API server, which validates access and returns track metadata along with a CDN signed URL for the requested bitrate.
  2. The client downloads audio chunks incrementally from the nearest CDN edge node using HTTP range requests rather than streaming a single monolithic file. The player begins decoding immediately upon receiving initial playable audio data and builds a steady-state buffer of 30 to 60 seconds ahead in the background.
  3. Gapless playback: The client engine prefetches the initial 5 seconds of the subsequent track while the current song is finishing its final bars.
  4. Crossfade transitions: The playback engine overlaps the trailing decibels of the current song with the rising audio curve of the next song based on user preferences.
  5. Audio codec format: Tracks are pre-encoded in OGG Vorbis across four fixed bitrates (24, 96, 160, and 320 kbps) to support diverse network conditions.
  6. Loudness normalization: ReplayGain metadata adjusts track gain client-side to ensure consistent perceived loudness across albums without re-encoding masters.

Music Catalog Service

The catalog service owns song, artist, and album metadata, serving a read-heavy workload that is aggressively cached across edge layers and in-memory stores.

  • It maintains the authoritative master database for all songs, albums, artists, genres, and associated copyright metadata.
  • Ingestion pipelines: Record labels and digital distributors submit tracks and metadata through automated batch ingestion workflows with format validation.
  • Relational hierarchies: Models structured relationships linking songs to albums and artists, mapping tracks to multiple genres, and connecting remix or featured artist references.
  • Database topology: MySQL cluster horizontally sharded by artist_id or song_id with multi-AZ read replicas to service high read concurrency.

Search Service (Elasticsearch)

The search service maintains an inverted index in Elasticsearch that is populated asynchronously from authoritative MySQL catalog writes via change data capture (CDC), providing fast full-text discovery with eventual consistency.

  • Provides full-text search across tracks, artists, albums, user playlists, and podcast episodes.
  • Query capabilities: Supports fuzzy matching (such as mapping "bettles" to "Beatles"), instantaneous prefix autocomplete, and did-you-mean spell correction.
  • Indexed document fields: Indexes title, artist name, album name, genre, synchronized lyrics where available, and popularity scores.
  • Search ranking function: Combines BM25 text relevance scores with global track popularity multipliers and recency decay curves.

Playlist Service

Playlists exhibit write-light and read-heavy access patterns, making them suitable for cache-aside architectures layered over distributed columnar storage.

  • Personal playlists: Created and modified by individual users, stored partitioned by user and playlist identifiers in Cassandra.
  • Collaborative playlists: Shared playlists where multiple authorized collaborators append, remove, and reorder songs using optimistic concurrency controls. Each playlist has an authoritative version field. Mutations route to the playlist's authoritative home write region: read version, submit mutation with expectedVersion, execute a conditional version update, apply positional track changes, and replicate asynchronously to follower read regions. When gaps in sparse position ordering (10, 20, 30) become exhausted, the service locally renumbers a bounded window of neighboring tracks.
  • Algorithmic playlists: Dynamic collections generated by the recommendation engine, including Discover Weekly, Daily Mix, and Release Radar.

Recommendation Engine: Deep Dive

Recommendations are pre-computed offline and cached in memory so that machine learning inference never blocks the synchronous audio playback path.

Collaborative Filtering

The system analyzes collective user activity through both user-user filtering (identifying listeners with similar playback patterns) and item-item filtering (connecting tracks frequently co-listened across sessions). Alternating Least Squares (ALS) matrix factorization decomposes the sparse user-song interaction matrix into latent preference vectors.

Content-Based Filtering

Deep learning models analyze raw audio features including tempo, musical key, acoustic energy, danceability, and acousticness. These acoustic profiles combine with genre classifications and artist graph metadata to recommend acoustically similar tracks regardless of existing stream volume.

Production Recommendation Ensemble

The recommendation stack blends multiple algorithmic signals into a coherent candidate generation pipeline:

  • Audio embeddings: Convolutional neural networks analyze raw spectrogram waveforms to generate 128-dimensional acoustic embedding vectors for new and cold-start tracks.
  • Natural language processing on playlists: Word2Vec-style sequence models treat playlists as sentences and tracks as words to learn implicit contextual similarities.
  • Knowledge graph traversal: Multi-hop graph networks capture relationships between artists, record labels, collaborators, and shared genres.
  • Multi-armed bandit exploration: The system deliberately introduces unfamiliar tracks to balance exploitation of known user preferences with ongoing taste discovery.

Offline Apache Spark batch jobs pre-compute the top 100 candidate recommendations per user and populate Redis clusters, allowing client feed requests to be served in under 50 milliseconds.

Spotify Connect (Cross-Device Playback)

Cross-device playback handoff relies on a centralized session registry so that audio state transfers smoothly between hardware endpoints without re-buffering delays.

  • Every connected device (mobile phone, desktop client, smart speaker, web player) maintains an active registration with the Device Session Service.
  • The user interface renders an active device selector allowing the user to redirect audio streams dynamically across local and remote hardware.
  • Transfer protocol: The controlling device issues a transfer command to the API Gateway, which notifies the target device over an open WebSocket or MQTT connection. The target device immediately resumes chunked streaming from the exact millisecond offset.
  • Bidirectional control: Any authenticated client can act as a remote control, adjusting volume, scrub positions, and playback queues on the active hardware target.

Device Session Service

The device session service tracks all active hardware endpoints per account, coordinating real-time Connect transfers while enforcing concurrency boundaries.

  • It maintains the active hardware state per account to distinguish between passive controllers and the single active streaming endpoint.
  • Redis session store:
    • session:{user_id}:active stores the device_id of the hardware currently receiving and decoding audio bytes.
    • session:{user_id}:devices holds a Redis set containing JSON payloads for all discovered devices with their type, human-readable name, and last seen heartbeat timestamp.
  • When playback transfers to a new device, the service updates the active key and dispatches an asynchronous notification to the destination hardware over MQTT or WebSocket.
  • If a device fails to transmit a heartbeat for 60 seconds, a background reaper removes it from the discovered devices set.
  • The service strictly enforces single-stream playback policies for standard accounts by validating the active key before issuing CDN range tokens to a new device.

Playback and Royalty Pipeline

Royalty accounting is processed asynchronously where playback events flow through distributed Kafka topics before feeding financial ledger systems.

The streaming pipeline tracks every listened second to power user analytics, billboard charts, and rights-holder royalty disbursements:

  1. The client writes playback events to a local durable SQLite buffer on the device. An asynchronous background worker transmits periodic retryable reports to POST /api/v1/playback/report with an immutable event_id, track_id, duration_listened_ms, completion status, bitrate quality, device_id, and session_id. If a network request fails, the client retries with exponential backoff, ensuring network dropouts never silently lose royalty records. Live audio decoding remains completely asynchronous and decoupled from ingestion.
  2. The API Gateway validates tokens, acknowledges the upload with an HTTP 202 status indicating pending processing (accepted: true, event_id: ..., processing_status: 'pending'), and produces the event to the Kafka topic playback-events, partitioned by user_id to maintain sequential FIFO ordering. The synchronous API intentionally does not declare royalty eligibility prior to asynchronous processing.
  3. An Apache Flink stateful streaming job processes incoming event streams:
    • Deduplication and idempotency: Downstream processing is idempotent. Flink enforces authoritative idempotency using the immutable event_id to deduplicate retried uploads, while a secondary 5-minute sliding window on (user_id, track_id, session_id) suppresses duplicate beacons.
    • Duration validation: Enforces the industry standard rule requiring at least 30 continuous seconds of playback before qualifying an event as a payable stream.
    • Fraud filtering: Identifies and filters bot behavior including inhuman listening velocities exceeding 500 tracks per hour, zero-skip loops, and rapid repeat plays from unverified accounts.
    • Eligibility determination and enrichment: Once an event passes duration, deduplication, and fraud verification, Flink marks it as royalty-eligible, joins against catalog caches to append artist IDs and record label licensing terms, and emits to royalty-events.
  4. Dedicated consumers of royalty-events distribute qualified records to PostgreSQL for daily track counts, ClickHouse for high-cardinality listening analytics, and the authoritative Royalty Ledger Database for financial auditing and payout settlement.
  5. A monthly Apache Spark batch job executes pro-rata calculations across the platform revenue pool, distributing royalties to record labels, publishers, and performing artists according to contractual ownership splits.
Loading...

Playback Event Bus (Kafka)

The event bus decouples event producers from consumers, buffering traffic spikes and establishing an immutable audit log for rights-holder reconciliation.

YAML
# Playback event bus topic specifications and consumer topology
topics:
  playback_events:
    name: "playback-events"
    partitions: 128
    partition_key: "user_id (guarantees per-user FIFO ordering)"
    retention: "7 days (immutable audit trail)"
    replication_factor: 3
    min_insync_replicas: 2
    producers:
      - "Playback Report Ingestion API (receives durable client uploads backed by local device buffer)"
    consumers:
      - name: "Flink royalty-aggregation"
        idempotency: "Authoritative idempotency deduplicates retried uploads using immutable event_id"
        deduplication: "Secondary (user_id, track_id, session_id) sliding window suppresses duplicate beacons"
        validation: "duration_listened_ms >= 30000 required for royalty qualification"
        fraud_filter: "Bot velocity tracking and repeat-loop detection"
        dead_letter_queue: "playback-events-dlq after 3 retries"
        lag_alert_threshold: "Consumer lag > 300 seconds triggers on-call alert"

  royalty_events:
    name: "royalty-events"
    partitions: 64
    partition_key: "artist_id"
    producers:
      - "Flink royalty-aggregation (emits only validated, fraud-cleared, royalty-qualified streams)"
    consumers:
      - "Royalty Ledger Database Writer"
      - "ClickHouse Listening Analytics"

  listen_history:
    name: "listen-history"
    partitions: 128
    partition_key: "user_id"
    producers:
      - "Playback Service (track start, skip, and completion events)"
    consumers:
      - "Cassandra listen_history Writer (writes to time-bucketed user partitions)"
      - "Spark Recommendation Batch Pipeline"

execution_paths:
  synchronous: "Client requests track metadata, receives signed CDN URL, and starts playback upon first playable audio (< 200 ms under normal networks)"
  asynchronous: "Client flushes durable playback events while the API responds with 202 Accepted ('pending'), and downstream Flink validates >=30s listens to emit qualified royalty events (2B daily streams, ~23K/sec)"

API Design

The API design specifies contracts for track metadata retrieval, catalog search, playlist mutations with collaborative reordering, personalized recommendations, and asynchronous playback reporting.

Client API Type Definitions

TypeScript domain interfaces defining audio models, playlist operations, and playback reporting structures:

TYPESCRIPT
// Audio streaming domain types and client service interface
export type AudioQuality = "24kbps" | "96kbps" | "160kbps" | "320kbps";
export type SearchEntityType = "track" | "artist" | "album" | "playlist";

export interface ArtistSummary {
  id: string;
  name: string;
  followerCount?: number;
}

export interface AlbumSummary {
  id: string;
  title: string;
  coverUrl: string;
  releaseDate?: string;
}

export interface TrackMetadata {
  trackId: string;
  title: string;
  artist: ArtistSummary;
  album: AlbumSummary;
  durationMs: number;
  streamUrl: string;
  previewUrl: string;
  availableQualities: AudioQuality[];
  loudnessNormalizationGainDb: number;
}

export interface SearchCatalogResponse {
  tracks: TrackMetadata[];
  artists: ArtistSummary[];
  albums: AlbumSummary[];
  hasMore: boolean;
}

export interface CreatePlaylistRequest {
  name: string;
  description?: string;
  isPublic: boolean;
}

export interface ModifyPlaylistTracksRequest {
  trackIds: string[];
  operation: "insert_after" | "append" | "delete";
  anchorTrackId?: string;
  expectedVersion: number;
}

export interface PlaybackReportEvent {
  eventId: string;
  trackId: string;
  durationListenedMs: number;
  completed: boolean;
  deviceId: string;
  sessionId: string;
  quality: AudioQuality;
  timestamp: number;
}

export interface PlaybackReportResponse {
  accepted: boolean;
  eventId: string;
  processingStatus: "pending" | "processed" | "rejected";
}

export interface MusicStreamingClient {
  getTrack(trackId: string, preferredQuality?: AudioQuality): Promise<TrackMetadata>;
  searchCatalog(query: string, types: SearchEntityType[], limit?: number): Promise<SearchCatalogResponse>;
  createPlaylist(request: CreatePlaylistRequest): Promise<{ playlistId: string; version: number }>;
  modifyPlaylistTracks(playlistId: string, request: ModifyPlaylistTracksRequest): Promise<{ version: number; trackCount: number }>;
  getRecommendations(seedTrackIds: string[], seedArtistIds: string[], limit?: number): Promise<TrackMetadata[]>;
  reportPlayback(report: PlaybackReportEvent): Promise<PlaybackReportResponse>;
}

Get Track and Stream URL Endpoint

Fetches metadata and resolves the signed CDN byte-range URL for the requested audio asset:

HTTP
GET /api/v1/tracks/trk_9b8f2a1c HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/json

{
  "track_id": "trk_9b8f2a1c",
  "title": "Bohemian Rhapsody",
  "artist": {
    "id": "art_queen_01",
    "name": "Queen"
  },
  "album": {
    "id": "alb_opera_1975",
    "name": "A Night at the Opera",
    "cover_url": "https://cdn.spotify.com/covers/alb_opera_1975.jpg"
  },
  "duration_ms": 354000,
  "stream_url": "https://cdn.spotify.com/audio/trk_9b8f2a1c/320.ogg",
  "preview_url": "https://cdn.spotify.com/preview/trk_9b8f2a1c.mp3"
}

Search Catalog Endpoint

Executes multi-entity fuzzy search across tracks, artists, and albums:

HTTP
GET /api/v1/search?q=bohemian+rhapsody&type=track,artist,album&limit=10 HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/json

{
  "tracks": [
    {
      "track_id": "trk_9b8f2a1c",
      "title": "Bohemian Rhapsody",
      "artist": "Queen",
      "duration_ms": 354000
    }
  ]
}

Playlist CRUD and Track Ordering Endpoints

Manages playlist creation and positional track insertions:

HTTP
POST /api/v1/playlists HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "Rock Classics",
  "description": "Essential rock tracks",
  "is_public": true
}

HTTP/1.1 201 Created
Content-Type: application/json

{
  "playlist_id": "ply_rock_01",
  "version": 1
}

POST /api/v1/playlists/ply_rock_01/tracks HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "track_ids": ["trk_9b8f2a1c", "trk_3a7b9c"],
  "operation": "append",
  "expected_version": 1
}

HTTP/1.1 200 OK
Content-Type: application/json

{
  "playlist_id": "ply_rock_01",
  "track_count": 2,
  "version": 2
}

# Stale version collision scenario (concurrent collaborator edit)
POST /api/v1/playlists/ply_rock_01/tracks HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "track_ids": ["trk_killer_queen"],
  "operation": "insert_after",
  "anchor_track_id": "trk_9b8f2a1c",
  "expected_version": 1
}

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "version_conflict",
  "message": "Playlist version mismatch (current version is 2). Refetch latest tracks and retry.",
  "current_version": 2
}

GET /api/v1/playlists/ply_rock_01/tracks?offset=0&limit=50 HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/json

{
  "items": [
    { "position": 10, "track_id": "trk_9b8f2a1c" },
    { "position": 20, "track_id": "trk_3a7b9c" }
  ],
  "total": 2
}

Get Recommendations Endpoint

Retrieves candidate recommendations generated from seed tracks and artists:

HTTP
GET /api/v1/recommendations?seed_tracks=trk_9b8f2a1c,trk_3a7b9c&seed_artists=art_queen_01&limit=30 HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/json

{
  "tracks": [
    {
      "track_id": "trk_killer_queen",
      "title": "Killer Queen",
      "artist": { "id": "art_queen_01", "name": "Queen" },
      "similarity_score": 0.94
    }
  ]
}

Report Playback Beacon Endpoint

Transmits client playback metrics for royalty accounting and history tracking:

HTTP
POST /api/v1/playback/report HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "event_id": "evt_9b8f2a1c_4f2b_1710000000",
  "track_id": "trk_9b8f2a1c",
  "duration_listened_ms": 32000,
  "completed": false,
  "device_id": "dev_mobile_4f2b",
  "session_id": "sess_89a12c",
  "quality": "320kbps",
  "timestamp": 1710000000
}

HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "accepted": true,
  "event_id": "evt_9b8f2a1c_4f2b_1710000000",
  "processing_status": "pending"
}

Historical Chart Rankings Endpoint

Fetches historical billboard rankings by category and date:

HTTP
GET /api/v1/rankings/history?category=pop&date=2026-03-01&limit=10 HTTP/1.1
Host: api.spotify.com
Authorization: Bearer <token>

HTTP/1.1 200 OK
Content-Type: application/json

{
  "category": "pop",
  "date": "2026-03-01",
  "rankings": [
    { "rank": 1, "track_id": "trk_9b8f2a1c", "stream_count": 14200000 }
  ]
}

Common Error Responses

Standardized error payloads returned during authentication or queue processing faults:

400 Bad Request: invalid input, missing required fields, or malformed JSON payload
401 Unauthorized: missing or invalid authentication token or API key
403 Forbidden: authenticated caller lacks required permissions for this resource
404 Not Found: requested resource ID does not exist
409 Conflict: duplicate write or version conflict, retry with a unique idempotency key
422 Unprocessable Entity: syntactically valid request failed semantic business validation
429 Too Many Requests: rate limit quota exceeded, client should honor Retry-After header
500 Internal Error: unexpected server failure, retry safely with an idempotency key
503 Service Unavailable: downstream dependency is unavailable or overloaded, retry with exponential backoff
202 Accepted: asynchronous job queued successfully, poll GET /jobs/{id} for completion status
408 Request Timeout: background job is still executing, continue polling status endpoint

Data Model

The data layer separates relational catalog records, high-write Cassandra columnar tables for user libraries and playlists, and immutable S3 object storage for multi-bitrate audio chunks.

MySQL: Song and Artist Catalog Metadata

Relational tables storing catalog items, indexed for relational joins and text search:

SQL
CREATE TABLE tracks (
    track_id        BIGINT PRIMARY KEY AUTO_INCREMENT, -- Internal surrogate primary key
    public_id       VARCHAR(32) NOT NULL UNIQUE,       -- String-safe external API ID (e.g. 'trk_9b8f2a1c')
    title           VARCHAR(256) NOT NULL,
    artist_id       BIGINT NOT NULL,
    album_id        BIGINT NOT NULL,
    duration_ms     INT NOT NULL,
    genre           VARCHAR(64),
    release_date    DATE,
    popularity      INT DEFAULT 0,                     -- 0-100
    explicit        BOOLEAN DEFAULT FALSE,
    audio_features  JSON,                              -- tempo, key, energy, etc.
    cdn_path        VARCHAR(512),
    created_at      TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_public_id (public_id),
    INDEX idx_artist (artist_id),
    INDEX idx_album (album_id),
    FULLTEXT idx_title (title)
);

CREATE TABLE artists (
    artist_id       BIGINT PRIMARY KEY AUTO_INCREMENT,
    public_id       VARCHAR(32) NOT NULL UNIQUE,       -- String-safe external ID (e.g. 'art_queen_01')
    name            VARCHAR(256) NOT NULL,
    bio             TEXT,
    image_url       TEXT,
    follower_count  BIGINT DEFAULT 0,
    genre           VARCHAR(64),
    INDEX idx_public_id (public_id)
);

CREATE TABLE albums (
    album_id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    public_id       VARCHAR(32) NOT NULL UNIQUE,       -- String-safe external ID (e.g. 'alb_opera_1975')
    title           VARCHAR(256) NOT NULL,
    artist_id       BIGINT NOT NULL,
    cover_url       TEXT,
    release_date    DATE,
    track_count     INT DEFAULT 0,
    INDEX idx_public_id (public_id)
);

Cassandra: User Library and Listen History

Columnar storage partitioned by user ID with clustering columns for chronological retrieval:

SQL
-- Idempotent user library keying around user_id + item_type + item_id
CREATE TABLE user_library (
    user_id     UUID,
    item_type   TEXT,        -- 'track', 'album', 'artist', 'playlist'
    item_id     TEXT,        -- String-safe external ID (e.g. 'trk_9b8f2a1c')
    added_at    TIMESTAMP,
    PRIMARY KEY ((user_id), item_type, item_id)
);

-- Time-bucketed listen history to prevent unbounded partition growth (>100MB)
CREATE TABLE listen_history (
    user_id         UUID,
    day_bucket      TEXT,        -- 'YYYY-MM-DD' bucket to bound partition size under 100MB
    listened_at     TIMESTAMP,
    track_id        TEXT,        -- String-safe external ID (e.g. 'trk_9b8f2a1c')
    duration_ms     INT,
    completed       BOOLEAN,
    context_type    TEXT,        -- 'playlist', 'album', 'radio', 'search'
    context_id      TEXT,
    PRIMARY KEY ((user_id, day_bucket), listened_at)
) WITH CLUSTERING ORDER BY (listened_at DESC)
  AND default_time_to_live = 7776000;  -- 90 days

Cassandra: Playlists and Positional Tracks

High-cardinality playlist partitions supporting rapid position lookups and reordering:

SQL
CREATE TABLE playlists (
    playlist_id     UUID PRIMARY KEY,
    owner_id        UUID,
    name            TEXT,
    description     TEXT,
    is_public       BOOLEAN,
    follower_count  INT,
    track_count     INT,
    version         INT,         -- Authoritative version counter for optimistic concurrency
    cover_url       TEXT,
    created_at      TIMESTAMP,
    updated_at      TIMESTAMP
);

CREATE TABLE playlist_tracks (
    playlist_id     UUID,
    position        INT,         -- Sparse gap indexing (e.g. 10, 20, 30) with local renumbering
    track_id        TEXT,        -- String-safe external ID (e.g. 'trk_9b8f2a1c')
    added_by        UUID,
    added_at        TIMESTAMP,
    PRIMARY KEY (playlist_id, position)
);

S3: Multi-Bitrate Audio Storage Layout

Object storage key convention and bitrate ladder per catalog track:

YAML
# S3 object storage layout for multi-bitrate audio assets
bucket: "spotify-audio"
key_pattern: "/{track_id}/{quality}.ogg"
objects:
  - path: "/{track_id}/24.ogg"
    bitrate: "24 kbps"
    format: "OGG Vorbis"
    target: "Ultra-low bandwidth cellular or preview"
  - path: "/{track_id}/96.ogg"
    bitrate: "96 kbps"
    format: "OGG Vorbis"
    target: "Default cellular streaming tier"
  - path: "/{track_id}/160.ogg"
    bitrate: "160 kbps"
    format: "OGG Vorbis"
    target: "Standard Wi-Fi streaming tier"
  - path: "/{track_id}/320.ogg"
    bitrate: "320 kbps"
    format: "OGG Vorbis"
    target: "High fidelity premium tier"
  - path: "/{track_id}/preview.mp3"
    duration: "30 seconds"
    format: "MP3"
    target: "Unauthenticated catalog browsing preview"

Redis: Pre-Computed Recommendation Cache

In-memory cache structures storing weekly Discover lists with TTL expirations:

YAML
# Redis cache layout for pre-computed user recommendations
key_pattern: "reco:{user_id}:{feed_type}"
data_type: "LIST"
item_type: "track_id (public string ID, e.g. trk_9b8f2a1c)"
ttl_seconds: 604800  # 7 days (refreshes on weekly batch generation)
example_key: "reco:usr_8921a:discover_weekly"
retrieval_command: "LRANGE reco:{user_id}:discover_weekly 0 29"

Kafka: Partition Topology Specifications

Topic partitioning strategies ensuring per-user ordering and consumer isolation:

YAML
# Kafka event topics, partition keys, and consuming services
topics:
  - topic: "playback-events"
    partitions: 128
    partition_key: "user_id"
    retention: "7 days"
    target_consumer: "Flink royalty aggregation, duration qualification, and deduplication"
  - topic: "royalty-events"
    partitions: 64
    partition_key: "artist_id"
    retention: "30 days"
    target_consumer: "Royalty Ledger Database writer and financial payout settlement"
  - topic: "listen-history"
    partitions: 128
    partition_key: "user_id"
    retention: "90 days"
    target_consumer: "Cassandra listen_history writer (bucketed) and Spark recommendation batch pipeline"

Fault Tolerance

Audio streaming architectures must survive CDN edge outages, database failovers, and transient network disconnects without interrupting active playback.

ConcernSolution
CDN edge failureDeploy a multi-CDN strategy with automatic DNS routing to an alternate CDN or regional origin shield
Playback interruptionClient buffers 30 to 60 seconds ahead to absorb transient network drops without stuttering
Metadata database failureFail over to MySQL read replicas while client applications serve cached catalog records locally
Recommendation service outageFall back to pre-cached recommendations in Redis or default to global top-K popularity lists
Audio file corruptionVerify chunk SHA-256 checksums at ingest and pull from immutable master audio files in cold storage

Resilient Client Playback Controls

The client audio player implements defensive strategies to guarantee uninterrupted sound during degraded network conditions:

  • The player downloads 30 to 60 seconds of audio ahead of the active playback scrub position.
  • When CDN bandwidth degrades, the client adaptive bitrate algorithm steps down progressively across chunk boundaries from 320 kbps to 160 kbps and 96 kbps.
  • If the network connection drops entirely, the player continues streaming from local buffer storage.
  • Dedicated offline mode enables users to play pre-downloaded, DRM-licensed albums without any active cellular or Wi-Fi connection.

Additional Considerations

Advanced system design interviews explore content identification, royalty distribution fairness, lossless compression codecs, offline cryptographic license checks, and cross-system architectural linkages.

Audio Fingerprinting and Content Identification

When record labels and independent creators upload new tracks, the ingestion pipeline generates unique acoustic fingerprints to enforce licensing compliance and prevent copyright violations.

  • The system computes robust acoustic hashes using Chromaprint or peak spectrogram landmarks to identify duplicate uploads, unauthorized covers, and modified audio masters.
  • Ingestion workers compare new fingerprints against indexed rights catalogs to flag licensing conflicts before tracks publish to search indices.
  • The same acoustic fingerprint index powers mobile recognition features allowing users to identify unknown songs playing in ambient environments.

Royalty Calculation and Settlement System

Royalty systems enforce strict financial auditing rules to convert raw stream events into legally compliant creator payouts.

  • Every validated listen lasting at least 30 continuous seconds qualifies for pro-rata royalty calculation.
  • Pro-rata pool model: The platform pools subscription and advertising revenues within each regional territory, allocating funds based on an artist's exact proportion of total qualified platform streams.
  • Audited data pipeline: Client play events stream through Kafka into stateful Apache Flink jobs that validate listens and write immutable accounting rows to the authoritative Royalty Ledger Database.

Audio Codecs and Transcoding Formats

Selecting the appropriate audio compression codec balances perceived acoustic quality, decoding CPU overhead on mobile devices, and CDN bandwidth expenditures.

  • Codec trade-offs: OGG Vorbis provides open royalty-free encoding for standard tiers, AAC ensures optimal hardware decoding across iOS devices, and FLAC provides lossless bit-for-bit fidelity.
  • High-fidelity lossless streaming: Delivering CD-quality FLAC streams at 1,411 kbps increases egress bandwidth by over 4x compared to standard 320 kbps lossy streams.
  • Dynamic loudness normalization: Ingestion workers calculate ReplayGain metadata, enabling client decoders to maintain uniform sound pressure across disparate musical eras and mastering styles.

Offline Downloads and Content Protection

Offline mode enables authenticated users to download full audio files to local storage while enforcing strict DRM expiration policies.

  • Downloaded tracks are retrieved via short-lived signed CDN download URLs backed by origin S3 and stored encrypted on the device filesystem using AES-128 or AES-256 encryption.
  • Client applications acquire a device-bound DRM license token (renewed every 30 days via network check-in) governing local hardware decryption and active subscription entitlement verification.
  • Native DRM integrations such as Google Widevine on Android and Apple FairPlay on iOS prevent extraction of raw audio streams from hardware decoders.
  • The local storage manager monitors disk usage and automatically purges downloaded tracks that have not been played for over 30 days.

Playback Queue and Cross-Device Synchronization

The user's upcoming play queue, shuffle seeds, repeat settings, and elapsed playhead position are persisted server-side in Redis.

  • Queue state synchronizes across client devices in near real-time using persistent WebSocket connections.
  • When a user initiates Spotify Connect to hand off playback between hardware targets, the server transfers the full playback state to resume decoding at the identical millisecond offset.
  • Collaborative queue sessions allow multiple users on the same Wi-Fi network to add tracks to a shared playback sequence.

Royalty Stream Aggregation Pipeline

Client devices record listening metrics to a local durable buffer and flush reports to the ingestion API, which writes them directly to the playback-events Kafka topic. Apache Flink validates that listening time reached at least 30 continuous seconds, deduplicates retries via the immutable event_id, applies contractual record label splits, and publishes qualified streams to royalty-events before writing audit records to the authoritative Royalty Ledger Database for financial payouts. This workflow operates completely asynchronously so that live audio playback never waits on ledger writes. Authoritative event deduplication using the immutable event_id paired with a 5-minute sliding window over (user_id, track_id, session_id) prevents client retry inflation and duplicate beacons from skewing accounting totals.

Related Problems and Concepts

Music streaming shares large-scale media delivery and edge caching principles with Video Streaming Platform (YouTube/Netflix) and Podcast Delivery Platform. Asynchronous event ingestion and stream deduplication closely mirror architectures explored in Distributed Message Broker and Distributed Stream Processing. Hardware device session synchronization and presence tracking align with User Presence System, while candidate generation connects to Recommendation System and Video Recommendation Engine. For foundational mechanics, explore CDN and Edge Delivery, Caching Patterns and Invalidation, Sharding and Partitioning, Kafka Architecture and Guarantees, and System Design Interview Patterns.

Interview Walkthrough

  • 25-Minute Interview Strategy

    Prioritize CDN chunked delivery and catalog separation before exploring staff-level multi-region origin shields or ClickHouse listening analytics and immutable royalty ledgers.

    • Functional and Non-Functional Requirements (3 min)
    • CDN Chunked Audio Delivery with Range Requests (7 min)
    • Catalog Metadata and Playlist Caching Architecture (6 min)
    • Asynchronous Royalty Stream Pipeline (5 min)
    • Offline Recommendation Serving Strategy (4 min)
  • Separate discovery and catalog browsing from audio playback delivery early in the discussion using System Design Interview Patterns, emphasizing their fundamentally different latency and caching profiles.
  • Detail chunked audio delivery through CDN and Edge Delivery using HTTP range requests and adaptive bitrate stepping, explaining how 5-second chunk prefetching guarantees smooth playback under fluctuating mobile connectivity.
  • Structure playlist and user library persistence across horizontally sharded Cassandra tables combined with Redis cache-aside layers referenced in Caching Patterns and Invalidation.
  • Walk through royalty stream aggregation using Kafka Architecture and Guarantees and stateful Flink workers to enforce the 30-second listening threshold and deduplicate client retries asynchronously.
  • Explain that recommendations follow the candidate generation pattern explored in Recommendation System, using offline Spark batch matrix factorization and Redis caching so ML inference never blocks the synchronous audio playback path.
  • Address the common architectural anti-pattern of routing audio bytes through backend application servers, demonstrating that origin storage belongs in object storage shielded by multi-region CDN edge PoPs.
  • Quantify aggregate network egress using Back-of-the-Envelope Estimation, calculating that 50M concurrent listeners streaming at 256 kbps generate 12.8 Tbps of peak edge throughput and roughly 10M chunk requests per second at 5-second intervals, with origin shields absorbing cache misses down to ~1M origin requests per second.

Engineering Trade-offs

Interviewers will probe your choices on streaming protocols, adaptive quality switching, shuffle randomness, and collaborative state reconciliation.

Audio Streaming: How Chunks Are Delivered

Audio clients rely on HTTP byte-range requests to begin decoding immediately after downloading initial playable audio, eliminating the delay of monolithic file downloads:

HTTP
GET /audio/trk_9b8f2a1c/320.ogg HTTP/1.1
Host: cdn.spotify.com
Range: bytes=0-262143
User-Agent: SpotifyMobile/8.8.0

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-262143/14160000
Content-Length: 262144
Content-Type: audio/ogg
Cache-Control: public, max-age=31536000, immutable
ETag: "trk_9b8f2a1c_320_p0"
YAML
# HTTP byte-range streaming mechanics vs monolithic downloads
range_request_rationale:
  byte_to_duration_math: "At 256 Kbps, 1 second of audio is 32 KB. A 5-second chunk is roughly 160 KB (5s * 256 Kbps / 8). A 256 KB chunk represents roughly 8 seconds of audio (256 KB * 8 / 256 Kbps = 8s)"
  startup_latency_reconciliation: "Playback begins as soon as initial frame headers and first playable data arrive, targeting < 200 ms time-to-first-playable-audio on normal networks rather than waiting for a full 5-second chunk"
  steady_state_buffering: "Once playback begins, the client issues sequential 5-second range requests in the background, maintaining a 30 to 60 second steady-state buffer"
  arbitrary_seeking: "When a user scrubs to 3:00, the player directly requests the byte offset corresponding to 3:00 without downloading earlier audio"
  egress_cost_control: "When users skip tracks after 30 seconds, only audio buffered to date is transferred from CDN edge nodes"
  fault_tolerance: "Network dropouts resume downloading from the exact last byte received without restarting the song"

client_prefetch_policy:
  concurrency_model: "While playing chunk N, dispatch background HTTP range requests for chunk N+1"
  headroom_target: "Maintain 30 to 60 seconds of buffered audio ahead of current playhead"
  degradation_threshold: "If buffer headroom falls below 10 seconds, downshift to lower bitrate tier (such as 320 kbps down to 160 kbps)"
Loading...

Adaptive Bitrate for Audio

Unlike video streaming which uses complex HLS or DASH manifests with server-side packaging, audio streaming relies on lightweight client-side network probing to transition across pre-encoded variant files at chunk boundaries:

YAML
# Adaptive bitrate mechanics for audio streaming based on network probing
bandwidth_measurement:
  heuristic: "Client calculates effective throughput as chunk_size divided by download_time"
  switching_ladder:
    - condition: "Measured throughput exceeds 500 kbps"
      stream_target: "320 kbps (Very High fidelity tier)"
    - condition: "Measured throughput between 200 kbps and 500 kbps"
      stream_target: "160 kbps (High quality default tier)"
    - condition: "Measured throughput between 100 kbps and 200 kbps"
      stream_target: "96 kbps (Normal quality cellular tier)"
    - condition: "Measured throughput falls below 100 kbps"
      stream_target: "24 kbps (Low quality preview tier or pause to rebuffer)"

switching_invariants:
  transition_boundary: "Quality shifts occur strictly at chunk boundaries and never mid-chunk"
  decoder_continuity: "The OGG Vorbis decoder dynamically accommodates differing bitrates without pipeline re-initialization"
  listener_experience: "The user experiences subtle acoustic refinement without audible gaps or playback stalls"

pre_encoded_catalog_storage:
  stored_variants_per_track:
    - "{track_id}/24.ogg"
    - "{track_id}/96.ogg"
    - "{track_id}/160.ogg"
    - "{track_id}/320.ogg"
  caching_profile: "CDN edge PoPs cache pre-encoded files with high hit ratios on 160 kbps and 320 kbps tiers"
  architectural_tradeoff:
    dynamic_transcoding: "Adds latency to initial chunk delivery and prevents efficient CDN edge caching"
    static_pre_encoding: "Trading inexpensive S3 storage for deterministic latency and optimal edge cacheability"

Shuffle Algorithm: Why Naive Random Is Wrong

True uniform random shuffles (such as Fisher-Yates) frequently produce consecutive clustering of songs by the same artist or genre, violating human expectations of randomness. Spotify implements a dithered shuffle algorithm that spaces artists evenly with small random offsets:

TYPESCRIPT
// Spotify dithered shuffle algorithm to avoid artist clustering
interface QueueTrack {
  id: string;
  artistId: string;
  genre: string;
}

export function ditheredShuffle(tracks: QueueTrack[]): QueueTrack[] {
  // 1. Group tracks by artist to prevent consecutive clustering
  const artistMap = new Map<string, QueueTrack[]>();
  for (const track of tracks) {
    const group = artistMap.get(track.artistId) ?? [];
    group.push(track);
    artistMap.set(track.artistId, group);
  }

  // 2. Distribute each artist's songs evenly across the total queue length
  const total = tracks.length;
  const positioned: { track: QueueTrack; position: number }[] = [];

  for (const [, group] of artistMap.entries()) {
    const interval = total / group.length;
    group.forEach((track, index) => {
      // 3. Apply bounded random jitter (+/- 0.4 interval) to avoid rigid predictability
      const jitter = (Math.random() - 0.5) * (interval * 0.4);
      positioned.push({ track, position: index * interval + jitter });
    });
  }

  // 4. Sort by jittered position to produce balanced, human-perceived randomness
  positioned.sort((a, b) => a.position - b.position);
  return positioned.map((item) => item.track);
}
YAML
# Comparison of naive random shuffle vs Spotify dithered shuffle
fisher_yates_naive_random:
  implementation: "Pure uniform permutation of queue elements"
  flaw: "Produces statistical clusters where tracks by the same artist play consecutively"
  user_perception: "Users perceive consecutive artist tracks as non-random behavior"

spotify_dithered_shuffle:
  step_1: "Group tracks by artist, genre, and acoustic tempo"
  step_2: "Calculate equal interval spacing across the entire queue length"
  step_3: "Apply bounded random jitter (+/- 0.4 interval) to prevent rigid repetition"
  step_4: "Sort tracks by their jittered coordinates to establish final queue order"
  outcome: "Evenly distributed artists and moods matching human expectations of randomness"

Collaborative Playlist: Concurrency Challenges

When multiple users edit a shared playlist concurrently, index-based positional mutations lead to corrupted positions and inadvertent song deletions. Anchored mutations resolve conflicts deterministically:

YAML
# Collaborative playlist mutation models, concurrency resolution, and multi-region writes
concurrency_conflict_scenario:
  initial_state: ["Track A", "Track B", "Track C", "Track D"]
  user_1_action: "Insert 'Track X' at index 3"
  user_2_action: "Remove element at index 2 (aiming to delete 'Track B')"
  index_based_failure:
    step_1: "User 1 write executes first: ['Track A', 'Track B', 'Track X', 'Track C', 'Track D']"
    step_2: "User 2 removes index 2: accidentally deletes newly inserted 'Track X' instead of intended 'Track B'"

intent_based_anchor_resolution:
  invariant: "Mutations reference relative track identifiers rather than volatile absolute array indices"
  user_1_mutation: "INSERT track_id='Track X' AFTER anchor_id='Track B'"
  user_2_mutation: "DELETE track_id='Track B'"
  deterministic_reconciliation:
    primary_result: "['Track A', 'Track X', 'Track C', 'Track D']"
    orphaned_anchor_fallback: "If anchor 'Track B' is deleted prior to insertion, append 'Track X' to playlist tail"

positional_indexing_strategy:
  sparse_gaps: "Positions use sparse integer gaps (10, 20, 30, 40) so insertions (e.g. 15) avoid re-indexing neighboring tracks"
  gap_exhaustion_handling: "When repeated insertions between adjacent tracks exhaust available integer gaps, the service locally renumbers a bounded window of adjacent items or falls back to fractional/lexicographic ordering"

optimistic_concurrency_and_multi_region:
  home_write_region: "Each playlist is assigned an authoritative home write region where all mutation requests are routed"
  optimistic_locking_flow:
    step_1: "Client reads playlist state and its authoritative version (e.g., version 2)"
    step_2: "Client submits mutation with expectedVersion: 2"
    step_3: "Home region executes conditional update (UPDATE playlists SET version = 3 WHERE playlist_id = ? IF version = 2)"
    step_4: "If update succeeds, apply positional track delta in playlist_tracks and increment version"
    step_5: "On version conflict, abort mutation, return 409 Conflict, and prompt the client to refetch latest state, re-anchor, and retry"
  cross_region_replication: "Committed updates asynchronously replicate to follower Cassandra clusters for low-latency read caching without split-brain anomalies"
  realtime_fanout: "API Gateway pushes JSON playlist patches over active WebSockets to synchronize connected viewers"

Stream Counting for Royalty Payments

Accurate playhead measurement directly governs artist compensation. Streaming platforms require distributed event deduplication and fraud verification pipelines before qualifying a listen for payment:

YAML
# Stream qualification criteria, fraud mitigation, durable delivery, and royalty settlement
stream_qualification_rules:
  minimum_playback_duration_ms: 30000
  authentication_requirement: "Authenticated user session required (unauthenticated previews excluded)"
  fraud_clearance: "Must pass real-time automated bot and streaming farm detection"

ingestion_and_processing_stages:
  stage_1_client_durable_buffer:
    resilience_model: "Client logs events to an encrypted local SQLite/LevelDB event buffer with an immutable event_id"
    retry_policy: "Dispatches retryable asynchronous uploads with exponential backoff, ensuring network failures never silently drop royalty events"
    synchronous_ack:
      status: "202 Accepted"
      response: "accepted: true, event_id: evt_..., processing_status: pending"
      semantics: "Server explicitly does not claim royalty_eligible: true synchronously, as qualification occurs downstream"
    payload:
      event_id: "evt_9b8f2a1c_4f2b_1710000000"
      track_id: "trk_9b8f2a1c"
      duration_listened_ms: 32000
      quality: "320kbps"
      device_id: "dev_mobile_4f2b"
      session_id: "sess_89a12c"
      timestamp: 1710000000
  stage_2_event_stream:
    broker: "Apache Kafka topic 'playback-events'"
    partition_key: "user_id to guarantee in-order delivery per listener"
  stage_3_flink_stream_processing:
    idempotency_and_deduplication: "Authoritative idempotency deduplicates retried uploads using immutable event_id, while a secondary 5-minute sliding window on (user_id, track_id, session_id) suppresses duplicate beacons"
    duration_verification: "Validates duration_listened_ms >= 30000 before qualifying event as a payable stream"
    fraud_mitigation:
      velocity_rule: "Flag accounts streaming over 500 tracks per hour"
      loop_detection: "Detect repeated track play loops exceeding 100 iterations from identical subnets"
      hardware_fingerprinting: "Reject simulated emulators and known scraper user-agents"
    aggregation_sink: "Emit hourly counts to PostgreSQL and publish qualified streams to Kafka 'royalty-events'"
  stage_4_financial_settlement:
    frequency: "Nightly Spark batch accounting run"
    pro_rata_formula: "artist_payment = (artist_streams / total_platform_streams) * net_territory_revenue_pool"
    ledger_persistence: "Write finalized debits and credits to immutable Royalty Ledger DB"

device_handoff_reconciliation:
  scenario: "User starts listening on smartphone and transfers stream to laptop via Spotify Connect"
  resolution: "Handoff initiates a distinct session_id, ensuring both genuine listening intervals receive proper credit while suppressing duplicate beacons within the same session"

💬Review

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...