Storage: 100M x 5MB = 500TB raw data
Streaming bandwidth:
Playlists:
POST /playlists
GET /playlists/{id}
PUT /playlists -> update/soft-delete playlist
req - {
status : 'InActive'
}
POST /playlists/{id}/song -> Add song
PUT /playlists/{id}/song -> soft-delete song from playlist
Playback:
GET /songs/{id}
Search:
GET /search?q=XYZ?cursor=id
-> returns: songs, artists, albums matching the query
GET /home-feed
-> returns users's personalized home feed (songs)
Like songs:
POST /songs/{id}/like
Acts as the entry point for all client requests.
Responsibilities:
Distributes traffic across multiple instances of all services to improve scalability and availability.
User Service/Playlist Service -> CRUD operations for both user and playlists
Streaming service:
Responsibilities
Search Service
Responsibilities
ElasticSearcgh
Event collection service
Responsibilties:
Kafka:
Flink:
Feature store / ML Model:
Feed/Recommendation Service:
Redis:
We use a hybrid SQL (PostgreSQL) + NoSQL (Cassandra) architecture.
Users
id
name
country (partition key)
Playlist
id
name
user_id (partition key)
status
PlaylistSongs
id
playlistId (partition key)
songId
position
Status
Songs
id
title
artist_id
album_id
duration
genre
-> artist id + album id as partition key
Artists
id
name
status
Albums
id
artist_id
songs[]
released_date
We will now deep dive in the following topics:
-> How to handle ~1B streaming requests daily
-> We never stream from backend, Instead of returning the entire song for playback whcih would be too heavy processing, we utilize ABR streaming + CDN, how does it work?
ABR streaming:
CDN
Recommendation Pipelein/generation
-> The most service dense feature of the system
-> Services like Event collection, kafka, feed/recommendation service, FLink, ML model and feature store work togetehr for the personlzied home feed generation.
How does the it work?
user123 : {
rock: {
affinity : 0.8,
skipRate: 0.2
likeRate:0.6
},
classical:{
affinity: 0.1,
skipRate: 0.7,
likeRate: 0.0
}
}
Failure Handling