Spotify System Design
LEGEND ━━ green: playback / key request path ━━ orange: ingestion path - - - orange dashed: async (events, queues, batch) - - - red dashed: error / retry path —— grey: sync call / control Fn / Dn / J…
On this board
- Spotify System Design
- LEGEND ━━ green: playback / key request path ━━ orange: ingestion path - - - orange dashed: async (events, queues, batch) - - - red dashed: error / retry path —— grey: sync call / control Fn / Dn / Jn … = step n of section
- audio: HTTP Range requests
- encode (D)
- PLAYBACK client → playback API → entitlement + session → audio delivery info → CDN / edge cache → audio buffer → decoder → player INGESTION artist / label / distributor → ingestion → metadata validation → rights → encoding workers → processed audio storage → CDN PERSONALIZATION listening events → e…
- A · Clients
- B · Edge & Traffic Management (an audio door and an API door)
- D · Music Ingestion & Audio Processing (how a master becomes a streamable track)
- Apps
- On the device
- DNS
- Regional Traffic Routing
- Audio CDN / Edge Network
- Artist / Label / Distributor
- Content Ingestion
- Metadata Validation
- Rights Management
- Encoding Queue
- Audio Processing Workers
- Mobile apps
- Player engine
- Artist / Label
- Audio Workers
- geo / latency based
- anycast, nearest PoP
- encrypted audio, artwork hit → regional → origin
- D1 · distributor uploads master + metadata
- D2 · stores the master (E)
- D3 · ISRC, UPC, credits
- D4 · territories, release window
- D5 · one job per track
- D6 · decode, loudness
- Android · iOS
- buffer, decrypt, decode
- Load Balancer
- API Gateway
- Auth Gateway
- Rate Limiting
- Service Discovery
- Available for Playback
- Catalog Index Update
- Processed Audio Storage
- Metadata + Artwork
- Audio Packaging
- Quality Profiles
- Web player
- Local audio cache
- Available to play
- Catalog Update
- Processed Storage
- Artwork
- L7, TLS, zones
- routing, versioning
- token check, client id
- per user / app / IP
- healthy instances per region
- D12 · playable in allowed markets
- D11 · catalog + search index (I)
- D10 · object storage + CDN origin
- D9 · images resized, metadata to catalog
- D8 · encrypt, segment, manifest
- D7 · a profile set per track
- browser
- recent + offline (K)
- control plane: auth, home, search, playlists, play commands → services (C). Audio never takes this door.
- Desktop app
- Event logger
- MASTER ≠ STREAMING ASSET master: lossless original, written once, rarely read. processed: encoded + encrypted, read millions of times via CDN.
- QUALITY PROFILES (approx.) low ~24 · normal ~96 kbps high ~160 · very high ~320 kbps lossless FLAC 24-bit/44.1 kHz (Premium) · web player: AAC
- ALBUM ARTWORK resize + compress to sizes → artwork storage → image CDN new artwork = new URL
- WORKER FAILURES + RETRIES worker dies → job visible again idempotent by (track, profile) n failures → dead-letter queue
- C · Core Backend Services (stateless, each scales alone)
- Windows · macOS
- batched, offline queue
- User & Identity
- Music Catalog
- Playback
- Smart TVs & speakers
- Connect client
- Authentication
- User Profile
- Artist
- Playback API
- Session Manager
- E · Music Storage & Content Delivery (audio bytes and metadata live in different places)
- living-room devices
- heartbeats, commands (G)
- login, OAuth tokens
- name, country
- source of truth (D)
- bio, images
- entry point (F)
- who plays what, where
- Master Audio
- Processed Audio
- Regional cache
- Edge PoPs
- Client buffer
- Connected audio
- Subscription
- Account Mgmt
- Album
- Track Metadata
- Playback State
- Audio Delivery
- talks to: API (B) · audio CDN (E) events → pipeline (L)
- lossless originals, restricted
- encoded + encrypted, CDN origin
- mid tier, shields origin
- hot tracks live here
- fetch by range (F7–F9)
- cars, consoles, watches
- plan → entitlements
- settings, family
- tracklist, release
- ids, ISRC, duration
- position, queue
- file ids, CDN URLs
- Track Metadata DB
- Artwork Storage
- Device Mgmt
- Availability
- Device Sync
- PLAYS BY POPULARITY head: few tracks, most plays → cached at the edge long tail: rarely played → regional cache or origin
- track, album, artist, ISRC (C)
- object storage → image CDN
- registered devices
- rights per market
- Connect-style (G)
- how audio gets served: metadata = small rows via the APIs (C) · audio = big immutable files via the CDN new encode = new file id → caches never need invalidating
- Library & Playlists
- Discovery
- Other
- Playlist
- User Library
- Music Search
- Recommendation
- Notification
- Lyrics
- CRUD, versions (H)
- saves, follows
- query → results (I)
- candidates (J)
- push, email
- time-synced lines
- Liked Songs
- Social Graph
- Ranking
- Home Feed
- Analytics
- Content Moderation
- per-user set
- follows, friends
- order per user
- shelves, cached
- events → (L)
- reports, policy
- Listening History
- Radio / Autoplay
- plays per user (L)
- what plays next
- sync, on the request path: Playback API → Subscription, Availability, Session Mgr, Audio Delivery Home Feed → precomputed recs · Search → index async, through the event stream (L): plays → History, Analytics, rec features playlist edits → followers, search index · nothing on the play path waits for…
- F · Music Playback & Streaming (control plane first, then data plane)
- G · Cross-Device Playback Sync (Connect-style: syncs control, not audio)
- Control plane · HTTPS API, small JSON
- User selects track
- Playback request
- Auth + entitlement
- Availability check
- Delivery info returned
- Phone
- Device Sync service
- session (one per user, versioned) { track_id: "…", position_ms: 83200, playing: true, volume: 0.6, active_device: "desktop-7", version: 42 }
- Delivery info
- F1 · tap, or remote cmd (G)
- F2 · POST /play → Playback API
- F3 · token valid? Premium?
- F4 · active device, queue
- F5 · market, licence, explicit
- F6 · signed CDN URLs
- owns the active device
- persistent connection
- Desktop
- Device Registry
- response goes back to the client
- phone plays; desktop opens → registry lists phone + speaker desktop taps "transfer" → compare-and-set v42 → v43 phone stops; desktop fetches audio from its own CDN edge
- Data plane · audio bytes from the CDN, never through the API
- Client requests audio
- CDN / edge cache
- Buffer + decode
- Playback begins
- Playback events (async)
- History + analytics
- opens the app
- online devices
- Request audio
- Playback events
- Smart speaker
- Session Manager (F4)
- NO DUPLICATE PLAYBACK one active device per session, enforced server-side; stale commands rejected by version