Netflix Viewing History on Cassandra
Netflix stores per-user viewing history in Cassandra partitioned by user_id, accepting eventual consistency because a few seconds of stale progress data is operationally acceptable while write availability across regions is not negotiable.
Netflix's viewing history tracks what a user has watched, how far they got, and when they last interacted with each title. Every play event is a write; reads are per-user lookups for the "continue watching" row and recommendation inputs. Cassandra partitioned by user_id co-locates all of a user's history on a single partition set, enabling efficient point lookups. Netflix runs Cassandra across multiple AWS regions with eventual consistency: the tradeoff is deliberate: stale progress data for a few seconds is acceptable, but write unavailability during a regional failure is not.
Scale at Decision Point
Users
~25M subscribers globally (2011, at time of Cassandra adoption)
Data Volume
Every play event persisted: billions of viewing history rows across all users
Request Rate
Write-heavy during peak viewing hours; read-heavy during login and browse sessions
Multi-region Cassandra clusters on AWS; tunable consistency per operation
Architecture Evolution
Initial Architecture
Relational database (Oracle) for viewing history storage. Single-region deployment with replication. Write throughput bounded by relational write path. Schema changes required coordinated migrations across large tables.
- Relational primary write ceiling cannot sustain global write volume at Netflix scale
- Single-region deployment cannot survive regional AWS failures without RPO impact
- Schema migrations on large history tables require maintenance windows
Evolved Architecture
Cassandra with partition key user_id, clustering key (title_id, event_timestamp). Multi-region deployment with LOCAL_QUORUM writes for latency and eventual consistency across regions. Chaos engineering (Chaos Monkey, Chaos Kong) validates resilience continuously. EVCache (memcached-based) layer caches hot user history reads.
- Eventual consistency: viewing progress can appear stale for seconds to minutes after a write
- Cassandra does not support cross-partition aggregations: analytics require a separate pipeline
- Wide partitions for highly active users can create read hotspots
Key Transitions
Trigger
Oracle write throughput ceiling could not sustain Netflix's global write volume as subscriber count grew. Single-region relational deployment created recovery time risk during regional AWS failures.
Before
Oracle relational store: single region, bounded write throughput
After
Cassandra multi-region cluster: partition key user_id, eventual consistency
Outcome
Write throughput scaled horizontally with Cassandra node count. Multi-region deployment eliminated single-region failure as a catastrophic risk. Cassandra became Netflix's primary operational data store over the following years.
Lessons
- Eventual consistency is the correct tradeoff for viewing history: stale progress data is a minor UX issue, not a correctness failure
- Design for the failure mode of a full AWS regional outage from the start: retrofitting multi-region is expensive
Trigger
Cassandra's resilience properties could only be trusted if tested under real failure conditions. Static disaster recovery plans decay; only continuously exercised failover paths remain reliable.
Before
Untested resilience: failover paths validated only in planned DR exercises
After
Continuous chaos engineering: random instance failures injected in production daily
Outcome
Netflix confirmed that Cassandra's replication model tolerated random node failures in production without user-visible impact. Engineering teams were forced to write services that degraded gracefully rather than failing hard.
Lessons
- Only failures that happen in production regularly are failures your system is actually prepared for
- Chaos engineering shifts the culture from 'this should not fail' to 'this will fail: does it recover?'
Key Lessons
Match consistency level to the actual correctness requirement of the data
Viewing progress does not need strong consistency. If Netflix shows you at 47:32 in an episode when you are actually at 47:35, that is a minor UX issue. Requiring strong consistency here would trade write availability for a marginal improvement that users cannot perceive.
Applicable when: You are choosing a consistency level and the data does not require exact correctness for user experience to be acceptable
Partition key selection determines write distribution: user_id is usually correct for per-user data
Cassandra partitions by user_id co-locate all of a user's viewing history on a predictable set of nodes. This enables efficient single-node reads for the continue-watching use case and distributes writes across the cluster by user activity level.
Applicable when: You are storing per-user data where the dominant access pattern is a single user's full record
Test your resilience continuously: DR plans that are never exercised are not resilience
Netflix's Chaos Monkey approach forced engineering teams to build services that handled node failures gracefully. Cassandra's replication model provided the redundancy; chaos engineering validated that the application layer used it correctly.
Applicable when: You are operating distributed stateful infrastructure and need to trust your resilience properties in production
Technologies
Patterns
Failure Modes Encountered
Related Scenarios
Sources
- Engineering BlogScaling Time Series Data Storage, Part I (Netflix viewing history on Cassandra) (2016)
3 sources are pending verification and have been hidden until a followable citation is available.