A look at how Spotify works. Spotify streams to roughly 600 million monthly active users across 100 million tracks, and the parts that look hardest (audio delivery at planet scale) are actually the easy part. The hard part, and the architectural bet Spotify made early, is keeping the recommendation surface honest: a per-user play history in Cassandra, scored nightly by collaborative-filtering models that don’t have access to the audio itself.

How Spotify Works: The problem at scale
Spotify streams to ~600 million users with an expectation of sub-second time-to-audio and zero buffering. Audio assets are large (a 3-minute song at 320 kbps is ~7 MB), 100 million tracks exist, and each user expects a personalized feed and a working recommendation system that knows what they’ll like next. The architecture has two unrelated problems: delivery (get the right bytes to the right user fast) and discovery (figure out what to play next). Spotify solves them with two completely different systems.
The core architecture
Delivery: when a user plays a track, the Spotify client calls the API + Auth layer, which forwards to the Playback Router. The router resolves the track to its CDN URL (every track is pre-encoded at multiple bitrates: 96/128/160/320 kbps Ogg Vorbis or OPUS, depending on platform) and hands the URL back. The client streams the audio directly from Akamai’s CDN, never touching Spotify’s own servers for the audio bytes themselves. Discovery: every play event is logged to Cassandra in a per-user play-history table. Offline batch jobs (nightly) score candidates per user using collaborative filtering on the play graph, plus audio-feature embeddings from Spotify’s Echo Nest acquisition. The ranked list feeds every recommendation surface: Discover Weekly, Daily Mixes, the home feed.
Audio CDN is not Spotify’s problem
This is the unobvious bet: Spotify doesn’t run its own audio CDN. Akamai serves the bytes. Spotify’s infra holds the catalog (track metadata, album art, lyrics), the user state (play history, playlists, follows), and the recommendations, the parts that differentiate the product. Akamai handles the high-bandwidth low-margin part. Most music services make the same choice, but Spotify was first to do it at scale, which is why a 50-engineer team could ship a global product without owning a single edge POP.
Cassandra for play history is the architecturally interesting choice
Play history is the canonical write-heavy dataset at Spotify: ~600 million users × ~50 plays/day = 30 billion plays/day. Each play is an immutable event; reads are always per-user and time-bounded (“give me this user’s last 100 plays”). This is exactly the workload Cassandra was designed for: writes are append-only to a partition key (user ID), reads are bounded range scans. The Cassandra cluster has to handle the burst of writes when users are active in the evening (in their timezone) and serve reads for the recommendation batch jobs at night. Sharding by user ID gives even distribution; time-series ordering gives efficient range reads.
This is also why recommendation personalization is “overnight” rather than real-time: the batch jobs that re-score a user’s taste profile run on the Cassandra data, not the live event stream. Real-time recommendation is starting to appear (Discover Weekly is still batch; the smart-shuffle feature is more reactive), but the bulk of the work is offline.
The one non-obvious insight
Spotify’s audio analysis, the Echo Nest-derived features (BPM, key, energy, danceability, acousticness), is computed once per track at ingest, not per play. That means when a brand-new song has zero play history, the recommendation system can still match it to users who like songs with similar audio features. This is what makes “Release Radar” work: a song released 2 hours ago, with zero global play history, can still be recommended to you because its audio features match your historical taste. Cold-start problem, mostly solved by pre-computed audio embedding.
Spotify is two systems: a thin delivery layer (Akamai CDN serving pre-encoded audio) and a heavy personalization layer (Cassandra play history + batch ML). The lesson is in their separation: they share no infrastructure, scale independently, and one can fail without breaking the other.
Continue learning: