Apache Cassandra is the canonical wide-column / Dynamo-style distributed database. Originally developed at Facebook for Inbox Search, open-sourced in 2008, and now the storage layer behind Netflix, Apple, Discord, Instagram, and Uber. Cassandra is built for write-heavy, multi-region workloads where availability and linear scalability trump strong consistency.
Cassandra combines Amazon Dynamo's distribution design (consistent hashing, replication to neighbouring nodes, gossip, tunable consistency) with Google Bigtable's storage model (a log-structured merge tree of immutable SSTables). The result is a database that accepts writes on any node in any region and keeps serving when nodes or whole data centres fail, in exchange for a query model that must be designed around partition keys up front.
Each node owns ranges of the token space (with virtual nodes, many small ranges). The partition key is hashed with Murmur3 to a token, and the replication strategy places copies on the next nodes around the ring, spread across racks, and in each data centre with NetworkTopologyStrategy. Any node can coordinate any request. Nodes learn cluster membership and state through gossip, and missed writes are repaired by hinted handoff, read repair, and scheduled anti-entropy repair.
ONE, QUORUM, LOCAL_QUORUM, ALL. Trade latency for consistency at the operation level.SELECT, INSERT, UPDATE — over a wide-column data model. No JOINs, no aggregations across partitions.LOCAL_QUORUM reads stay in-region.A Cassandra table is keyed by a partition key (which determines which node owns the data) plus optional clustering columns (which determine sort order within the partition). The right partition-key choice is the single most important design decision — bad keys produce hot partitions or cross-partition scans, both of which are pathological in Cassandra.
A write is acknowledged once it is in the commit log and memtable, so write latency is low and nearly constant. Updates and deletes are just newer cells (deletes are tombstones), resolved at read time by timestamp. Bloom filters let reads skip SSTables that cannot contain the partition, and compaction strategies (size-tiered, leveled, time-window) trade write amplification against read performance; time-window compaction suits time-series tables with TTLs.
In Cassandra you design one table per query. For "latest readings for a sensor on a given day", partition by sensor and day so partitions stay bounded, and cluster by time descending:
CREATE KEYSPACE iot WITH replication =
{'class': 'NetworkTopologyStrategy', 'dc1': 3, 'dc2': 3};
CREATE TABLE iot.readings_by_sensor_day (
sensor_id text,
day date,
ts timestamp,
temp_c double,
humidity double,
PRIMARY KEY ((sensor_id, day), ts)
) WITH CLUSTERING ORDER BY (ts DESC)
AND default_time_to_live = 7776000 -- 90 days
AND compaction = {'class': 'TimeWindowCompactionStrategy',
'compaction_window_unit': 'DAYS', 'compaction_window_size': 1};
INSERT INTO iot.readings_by_sensor_day (sensor_id, day, ts, temp_c, humidity)
VALUES ('s-17', '2025-06-01', '2025-06-01 12:00:00', 21.4, 0.48);
-- Efficient: one partition, already sorted
SELECT ts, temp_c FROM iot.readings_by_sensor_day
WHERE sensor_id = 's-17' AND day = '2025-06-01' LIMIT 10;
-- Rejected without ALLOW FILTERING: no partition key, would scan the cluster
-- SELECT * FROM iot.readings_by_sensor_day WHERE temp_c > 30;
If another query needs "all sensors above a threshold", create a second table keyed for that access pattern and write to both, often with a logged batch. Denormalization is the normal cost of Cassandra's predictable performance.
| Level | Replicas that must answer (RF=3) | Use when |
|---|---|---|
| ONE | 1 | Lowest latency; stale reads acceptable (metrics, logs) |
| LOCAL_QUORUM | 2 in the local DC | Default for most apps; consistent within a region |
| QUORUM | 2 of all replicas (across DCs: majority of total) | Cross-region consistency, higher latency |
| ALL | 3 | Rarely; any node down fails the request |
Reads and writes are strongly consistent when the replicas read plus the replicas written exceed the replication factor, for example LOCAL_QUORUM for both with RF=3 in one data centre. Lightweight transactions (IF NOT EXISTS) use Paxos for compare-and-set at a significant latency cost.
gc_grace_seconds.