Databases
Advanced 14 min read Databases

Cassandra and Wide-Column Stores

A column family obeying quorums, tombstones, and one partition key

Cassandra is an AP, log-structured, wide-column database. Your partition key plus clustering columns define a row's card; reads and deletes honor that physical organization or pay a full-cluster scan.

partition keywide rowcompactionquorumSSTabletombstone
Prerequisites: CAP Theorem Indexing
Before we start

What you will learn

  • Model with partition key + clustering columns, not random column access
  • Explain how reads apply SSTables and tombstones
  • Choose LOCAL_QUORUM against a failure model
Introduction

What is this?

Cassandra stores each row in a hash-partitioned way on one of many nodes by partition key; within a partition, clustering columns order the row. Writes are immutable appends to SSTables; reads merge SSTables and tombstones; deletes are writes of tombstones that compact away eventually.

Motivation

Why do you need it?

  • It is the default for write-saturated, high-availability event, and device data.
  • A mis-modeled partition key (low cardinality, hot key) makes a 'distributed' cluster behave like one node.
  • REQUIRED perspective: lesson 1 in wide-column modeling is knowing when your queries are allowed to be fast.
Think about it

Mental model

Imagine

A set of timeboxed ledgers, one ledger per user, appended in order

Think of

Cassandra partition with clustering key

A per-user partition key groups all the user's events; clustering by timestamp keeps them ordered. You can only quickly find what you can sort against that page.

Mechanics

How it works

  • Writes append to a memtable, then flush to immutable SSTables; compaction merges them in the background.
  • Replication factor R + consistency CL decides how many replicas ack; quorum (R/2 + 1) tolerates minority loss.
  • Deletes insert tombstones; ranges of tombstones are purged at compaction when older than gc_grace_seconds.
  • The partition key hashes to a token; nodes own token ranges that split into vnodes.
  • Local queries (secondary indexes, ALLOW FILTERING) are scans across partitions and are a known trap.

Write -> flushed SSTable -> read merge path.

Write
Flush
Read
Tombstones
Compaction
Reference

Key commands

CONSISTENCY LOCAL_QUORUM;

Require a quorum of local replicas for reads and writes.

SELECT * FROM events_by_user WHERE user_id = ? LIMIT 20;

A partition-scoped query the storage model actually favors.

nodetool repair -full;

Reconcile anti-entropy so replica divergence is repaired.

Hands-on

Examples

An order-preserving event table

An order-preserving event table
CREATE TABLE events_by_user (
user_id uuid,
ts timestamp,
payload text,
PRIMARY KEY (user_id, ts)
) WITH CLUSTERING ORDER BY (ts DESC);
-- Good: fetch last 50 events for a user
SELECT * FROM events_by_user WHERE user_id = ? LIMIT 50;
-- Expensive: scan every user's partition for 'recent'
SELECT * FROM events_by_user WHERE ts > ? ALLOW FILTERING;

The partition key localizes reads; the clustering column orders them. Querying across all partitions with ALLOW FILTERING defeats that design.

Real world

In production

  • A device fleet writes sensor events by device_id partition, auto-clustering by ts, at 100k writes/sec.
  • A high-volume alerting system stores alerts per service with a quorum read to avoid lost acks.
  • Time-bucketed tables (YEAR/MONTH) let teams drop old partitions instead of rolling huge deletes.
Guidelines

Best practices

  • Model partition by the entity your query starts from (user_id, device_id, service_id) and cluster by the ordering your query needs.
  • Set gc_grace_seconds consistent with your cadence of repairs; too-tight tombstone purging can resurrect deleted data.
  • Use quorum reads/writes for correctness-sensitive flows; LOCAL_ONE is for log-style tolerance of stalls.
  • Avoid unbounded per-partition growth: size, time-bucket, or paginate by clustering suffix.
Watch out

Common mistakes

  • Selecting WHERE ts range with no partition key — a cluster-wide scan that timeouts at production size.
  • Making an unbounded partition (all events into one user partition), creating a hot 100GB row.
  • Running heavy deletes without tombstone planning; cheap-looking deletes becomes hours of compaction.
When things break

Debugging tips

  • nodetool tablestats reveals large partitions and estimate_partition_size to catch hot keys.
  • High GC/compaction pauses follow tombstone-heavy deletes; check table tombstones and expiration.
  • Read repair racing that amplifies latency often points to low CL + replica inconsistency; raise CL before scaling harder.
Interviews

Interview checkpoint

Test yourself

Quick quiz

0/2
1

The natural query entry point in Cassandra is the…

2

A delete in Cassandra is actually a write of a tombstone marker.

Go deeper

Official documentation