Traffic estimations
Bandwith
Storage
Cache estimations
We will keep a SQL database for user information as well as song meta data. This SQL database will also keep the user_id, playlist, songs relationship. Basically a table for user and playlist, which indicates which playlist belongs to which user, as well as a playlist and song table, which indicates which songs belong to a particular playlist
We will then keep the music file itself in a cloud storage like google cloud, which is extremely scalable, allowing us to keep files that are quite big (5MB) in this case in a cloud storage
The most important question would be how can we play songs with as little latency as possible? In this case we will use Linked List as our main data structure to manage songs and the queues.
When a user starts using the app, it will create a Web Socket with the backend server. Once this connection is established. An entry in a HashMap is created, which uses the user_id as a key, and the Linked List data structure as the value. When a user clicks on a song, the backend system will start downloading the song from the cloud storage and return to the client. Concurrently, the server will check on the next song that it will download based on whether the user is playing from a particular playlist or not. For example if a user is playing from their 'Liked Songs' playlist, then the server will retrieve a list of songs in this particular playlist, next, if shuffle = false, then the next song is obvious, simply the next song in the list. However, if shuffle = true, then the server will maintain a Set, which is basically a set of song_ids that have been played, if played then dont play again, else queue it. If the user is not playing from any playlist, then the next song queued will be completely randomised. The server will continually download the next few songs and add them to the linked list, this is much much better than downloading the next song once the current song finishes, this allows the seemless transision from one song to the next. this can be done by another server, that will continually add songs to the back of the linked list.
However, how can we make this even more efficient? what we dont want to do is to download the entire song before returning the result to the user. what we want is to download the songs in CHUNKS. How can we do that? It all starts when a musician uploads their music onto the app. The music is then split into different smaller chunks before it is stored in the cloud storage. This is good because when a user plays a song, we can load up the first chunk and return it to the user (which can take less than 0.5 seconds) and then the client will start playing it, the server will continue to download subsequent chunks from the song, the order of chunks will be ensured by their order_id. This is better than having to download the entire song before returning to the client, which can take an upward of 5 seconds to do. Storing our music in chunks also does something else, we can store the chunks of a song in different cloud storages, this is a good data sharding strategy, this is because of trending / popular songs. If all the chunks of popular / trending songs are stored in 1 database, then this particular database will be overloaded, being able to distribute the chunks into more than 1 database is a good thing because that way the load is distributed to all databases.
How can we do even better? By using caches. For popular and hot songs, we want to prevent the querying of the chunks for these songs from the database as much as possible (as it is slow), what we want is to cache the chunks. However, what i suggest is to cache only the first 15-30 seconds of the songs instead of the whole song, that way, the 15-30 seconds allows the server to query the remaining chunks of the song from the database, this also allows more songs to be cached.
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
Allow users to private their playlists and songs if they want to. Allow users to add friends and see their playlists.