Why Cassandra
Cassandra combines ideas from Dynamo and Bigtable: massive footprints, high query volume, flexible sparse columns. It's open-source, runs in a cluster, and scales out horizontally. This deep dive covers what makes it attractive, how it works internally, and when to reach for it in an interview.
Keyspace · table · wide rows.
Consistent hash · vnodes.
LSM · append · compaction.
Access patterns first — no JOINs.
Data model
Keyspace — top-level unit (like a database in Postgres). Defines replication strategy.
Table — rows within a keyspace, with a schema and primary key.
Row — one record, keyed by primary key.
Column — name, type, value; sparse rows OK — not every row needs every column. Each column carries timestamp metadata; conflicts resolve via last-write-wins.
{
"keyspace1": {
"table1": {
"row1": { "col1": 1, "col2": "2" },
"row2": { "col1": 10, "col3": 3.0 },
"row3": { "col4": { "company": "Lettuce", "city": "Seattle" } }
}
}
}
Primary key
Every row is unique via a primary key — partition key(s) plus optional clustering key(s). Same concept as DynamoDB's primary key, shared 1:1.
- Partition key — determines which partition (and node) holds the row.
- Clustering key — sort order of rows within a partition.
-- Partition only
CREATE TABLE t (a text, b text, c text, PRIMARY KEY (a));
-- Partition + clustering
CREATE TABLE t (a text, b text, c text, PRIMARY KEY ((a), b))
WITH CLUSTERING ORDER BY (b ASC);
-- Composite partition key
CREATE TABLE t (a text, b text, c text, d text, PRIMARY KEY ((a, b), c));
Partitioning
Cassandra scales by partitioning data across cluster nodes using consistent hashing. Unlike hash(value) % num_nodes — which remaps most keys when nodes change and can skew load — consistent hashing maps values to a ring and walks clockwise to the first token/node. Adding or removing a node only remaps adjacent ranges.
Virtual nodes (vnodes) map multiple ring positions to each physical node for even load and flexible capacity (bigger machines can own more vnodes). See Consistent hashing for the full ring story.
Replication
Partitions replicate to multiple nodes for availability. With replication factor 3, Cassandra hashes the key, then scans clockwise for two additional vnodes — skipping vnodes on the same physical node so one host failure doesn't take multiple replicas.
- NetworkTopologyStrategy — production default; rack- and datacenter-aware.
- SimpleStrategy — clockwise scan only; fine for dev/test.
ALTER KEYSPACE lettuce WITH REPLICATION = {
'class': 'NetworkTopologyStrategy',
'dc1': 3, 'dc2': 2
};
Consistency
Cassandra is subject to the CAP theorem. No transactions or full ACID — only atomic, isolated row-level writes within a partition. You tune read/write consistency levels: how many replicas must respond (ONE through ALL).
QUORUM — majority (n/2 + 1) of replicas. QUORUM on both reads and writes guarantees overlap: with RF=3, 2 nodes participate in each operation, so at least one node seen on read also saw the write.
Query routing
Any node can act as coordinator. Nodes learn cluster topology via gossip, compute partition location from the partition key, and fan out to replicas per consistency level.
Storage model (LSM)
Cassandra favors write speed over read speed. Creates, updates, and deletes are append-style entries (deletes write tombstones). An LSM tree backs this — same family as DynamoDB-style engines. See Database indexing for LSM vs B-tree trade-offs. Metrics-oriented LSM + compression + time partitions: Time-series databases.
- Write hits commit log (WAL) for durability.
- Write goes to memtable (in-memory, sorted by primary key).
- Memtable flushes to immutable SSTable on disk.
- Reads: memtable first, then bloom filter + SSTables newest-first.
- Compaction merges SSTables and purges tombstones.
Gossip and fault tolerance
Nodes exchange cluster state via gossip — peer-to-peer, with seed nodes as guaranteed gossip hubs so sub-clusters don't form. Vector clocks (generation + version) let nodes ignore stale gossip.
Phi accrual failure detection convicts unresponsive nodes during gossip. Nodes aren't permanently "down" unless an admin decommissions them — intermittent failures shouldn't trigger full rebalancing.
Hinted handoff — when a coordinator can't reach a replica, it stores a short-lived hint so the write succeeds; delivers when the node returns. Long outages need repair/rebuild, not hints alone.
Query-driven data modeling
Relational modeling is entity-driven with normalization and JOINs. Cassandra is query-driven: design access patterns first, denormalize aggressively, one table per query shape. No JOINs, no foreign keys, single-table queries only.
- Partition key — keeps related reads on one partition (avoid scatter-gather).
- Partition size — hot or unbounded partitions hurt (Discord's lesson).
- Clustering key — sort order for timeline queries.
- Denormalization — duplicate data across tables for different access patterns.
Example: Discord messages
Channels are busy; users read recent messages in reverse chronological order. Original schema:
CREATE TABLE messages (
channel_id bigint,
message_id bigint,
author_id bigint,
content text,
PRIMARY KEY (channel_id, message_id)
) WITH CLUSTERING ORDER BY (message_id DESC);
message_id as Snowflake ID (time-sortable UUID) avoids primary-key collisions vs millisecond timestamps. Problem: mega-channels created partitions too large and growing forever. Fix — add a bucket (10-day window from Discord epoch) to the partition key:
CREATE TABLE messages (
channel_id bigint,
bucket int,
message_id bigint,
author_id bigint,
content text,
PRIMARY KEY ((channel_id, bucket), message_id)
) WITH CLUSTERING ORDER BY (message_id DESC);
Example: Ticketmaster seat browsing
Event seat map UX: users browse sections first, then individual seats. Event-wide partition with 10k+ seats forces heavy aggregation. Add section_id to partition key for seat-level queries; separate event_sections table denormalizes section totals and price floors for the venue map — eventual consistency is fine (UI shows "100+" not exact counts).
event_sections; seat drill-down reads tickets.CREATE TABLE tickets (
event_id bigint,
section_id bigint,
seat_id bigint,
price bigint,
PRIMARY KEY ((event_id, section_id), seat_id)
);
CREATE TABLE event_sections (
event_id bigint,
section_id bigint,
num_tickets bigint,
price_floor bigint,
PRIMARY KEY (event_id, section_id)
);
Advanced features
- Storage Attached Indexes (SAI) — secondary indexes with flexible queries; slower than partition-key lookups.
- Materialized views — Cassandra-maintained denormalized tables from a source table.
- Search plugins — ElasticSearch/Solr integration for full-text (see Elasticsearch).
Cassandra in an interview
When to use it
- Availability over strict consistency; high horizontal scale.
- High write throughput — metrics, logs, chat, IoT.
- Sparse/flexible schemas with clear, upfront access patterns.
When not to
- Strong consistency requirements, complex JOINs, ad-hoc analytics.
- You haven't defined access patterns — you'll paint yourself into a corner.
Cost and performance levers
Cassandra query-first design
Hot partition warning
Partition key = country when 80% traffic is one country → hotspot. Add bucket suffix or choose higher-cardinality key.
Failure modes to mention
Call out at least one dependency failure (DB down, cache stampede, queue lag, region outage) and your mitigation (timeouts, retries with jitter, degraded mode, circuit breaker).
Interview Q&A by level
Practice saying these out loud for Cassandra. Interviewers grade clarity and judgment more than buzzwords.
Match depth to the bar: define → trade off → operate. Don't dump principal answers in an entry-level screen.
Wrapping up
Cassandra is versatile but not universal. Its value shows up when query-driven schemas, partition keys, and LSM write paths match your access patterns. Internals — consistent hashing, replication, QUORUM, compaction — are what separate a name-drop from a defensible design.
Compare with PostgreSQL (interview default), Amazon DynamoDB (managed AWS alternative), write scaling context in Scaling writes, modeling trade-offs in Data modeling, and LSM depth in Database indexing.