Data Modeling and Schema Design
This domain tests whether you can design tables from access patterns rather than from entity relationships. Cassandra is a distributed partitioned store, so schema choices determine which queries are efficient and which fail. Expect partition-key design, clustering columns, denormalization, secondary indexes, SAI, materialized views, static columns, and collection usage.
Start from queries
List each query with its filters and sort order. One table usually serves one query. The partition key is hashed to a token, so it must be present in every efficient WHERE clause. Clustering columns order rows inside a partition and support range predicates on trailing clustering columns. A primary key is ((partition keys), clustering columns...). Choose a partition key with enough cardinality to spread load and a bound on partition size.
Denormalize deliberately
Duplicating data into query-specific tables is normal. Writes become multiple statements, so use a logged batch only when atomicity across tables matters; do not treat batches as a bulk-load performance tool. Secondary indexes suit low-cardinality columns and small result sets; SAI supports more flexible indexing but still does not replace a good partition key. Materialized views maintain an alternate query path but add write cost and operational caveats.
Worked example
Requirement: fetch the latest 50 readings for one sensor for one day, newest first. A table PRIMARY KEY ((sensor_id, day), reading_time) with clustering order by reading_time DESC works: sensor_id and day are equality-filtered, so the partition is bounded to one day, and reading_time supports the ORDER BY and LIMIT. Using PRIMARY KEY (reading_id) would scatter the query across all nodes. Using PRIMARY KEY (sensor_id, reading_time) without a day bucket could create an unbounded partition for a long-lived sensor. The bucket is part of the partition key, so queries must supply it.
Traps
Do not design from ER diagrams or normalize by habit. Do not use a low-cardinality partition key such as status; it creates hot partitions. Do not assume ALLOW FILTERING is a design fix. Avoid unbounded collections and very large partitions. Static columns are shared per partition, not per row; use them only when that semantic is correct.