Wide-column stores like Cassandra handle enormous write throughput by partitioning data across a cluster. Learn the partition-key/clustering-key model and why you design one table per query.
Wide-column stores (Cassandra, HBase, BigTable) are designed for huge write volumes and horizontal scale with no single point of failure. Data is spread across many nodes by a partition key, and every node can accept writes. This makes them the go-to for time-series, event logs, IoT telemetry, and any firehose of data that would overwhelm a single-primary relational database.
Why wide-column exists:
a relational DB has ONE primary for writes -> a write ceiling.
Cassandra has NO primary: every node accepts writes, data is spread
by PARTITION KEY across the ring, replicated for fault tolerance.
-> linear write scale (add nodes = more write throughput)
-> no single point of failure; AP by default (stays up under partition)
Use for: time-series, event/click streams, IoT, messaging, anything with
a relentless write firehose + known read patterns.The data model is defined by two parts of the primary key. The partition key decides which node stores a row and must be chosen so data and load spread evenly. The clustering key orders rows within a partition, enabling efficient range scans. Together they determine both scalability and which queries are fast — everything in Cassandra flows from this key design.
-- CQL: a table for "readings for a sensor, over time"
CREATE TABLE readings (
sensor_id text, -- PARTITION KEY: which node stores it (spread load)
reading_at timestamp, -- CLUSTERING KEY: orders rows within the partition
value double,
PRIMARY KEY ((sensor_id), reading_at)
) WITH CLUSTERING ORDER BY (reading_at DESC);
-- fast: all readings for one sensor, newest first (one partition, ordered)
SELECT * FROM readings WHERE sensor_id = 's-42' LIMIT 100;
-- partition key = high cardinality + even access; clustering key = your
-- sort/range dimension. Design decides scale AND which queries are possible.Because you can only query efficiently by partition key (and range on clustering columns), Cassandra has no ad-hoc queries or joins. The idiom is query-first taken to its extreme: you create a separate, denormalized table for each access pattern, writing the same data into several tables. Storage is cheap; slow reads are not. This feels wrong to a relational modeler and is exactly right here.
You can't "just query" Cassandra any way you like — only by partition key.
So you build ONE TABLE PER QUERY, duplicating data across them:
need "readings by sensor over time" -> table keyed by (sensor_id, time)
need "readings by region over time" -> table keyed by (region, time)
need "latest reading per sensor" -> table keyed by (sensor_id) upserted
Same data, written to 3 tables. Denormalization + duplication is the
DESIGN, not a smell. Storage is cheap; unindexed scans are forbidden.
Get the access patterns right up front — adding one later means a new table + backfill.Wide-column stores let you choose consistency per query by setting how many replicas must respond. You trade latency and availability against freshness: require one replica for speed, or a quorum for strong consistency. This per-operation control is powerful — write with a quorum where correctness matters, read with one where speed matters — and is a key reason these stores fit varied workloads.
-- Cassandra: consistency is per-query (replicas that must ack)
CONSISTENCY ONE; -- fastest, most available, may read stale
CONSISTENCY QUORUM; -- majority of replicas -> strong-ish consistency
-- the classic safe combo (with replication factor 3):
-- write QUORUM + read QUORUM -> reads always see the latest write
-- (write replicas + read replicas overlap)
-- tune per operation: critical write -> QUORUM; hot analytics read -> ONE.
-- You dial the CAP trade-off per query instead of once for the whole DB.