Implementing Column-Family Stores
1. Designing Column Families
| Concept | Detail |
| Keyspace | Top-level namespace (like DB) |
| Table (CF) | Collection of partitions |
| Partition key | Determines node placement |
| Clustering columns | Sort within partition |
| Columns | Wide-row; varying per partition |
Example: Cassandra Table
CREATE TABLE events_by_user (
user_id UUID,
event_ts TIMESTAMP,
event_id TIMEUUID,
payload TEXT,
PRIMARY KEY ((user_id), event_ts, event_id)
) WITH CLUSTERING ORDER BY (event_ts DESC, event_id DESC);
2. Modeling Wide Rows
| Pattern | Detail |
| Time-series per entity | Partition by entity_id, cluster by time |
| Bucket partition | (user_id, yyyymm) — limit partition size |
| Partition size limit | Target < 100 MB / 100k rows |
| Avoid unbounded growth | Reshard by time |
3. Designing Partition Keys
| Goal | Detail |
| Even distribution | High cardinality keys |
| Query-friendly | Single-partition reads where possible |
| Composite keys | (tenant_id, day) for bounded shards |
| Avoid hot partitions | No single key catching all writes |
4. Implementing Clustering Columns
| Use | Detail |
| Sort within partition | ASC / DESC defined in DDL |
| Range scans | Efficient — sequential on disk |
| Order matters | Equality only on prefix; range on last column |
5. Designing for Time-Series Data
| Tip | Detail |
| Bucket by day/hour | Prevent unbounded partitions |
| TimeWindowCompactionStrategy | TWCS — best for TS workloads |
| TTL on rows | Auto-expire old data |
| Clustering by ts DESC | Cheap "latest N" queries |
6. Modeling for Write-Heavy Workloads
| Property | Detail |
| LSM tree | Append-friendly architecture |
| No read-before-write | UPSERT semantics by default |
| Counter tables | Atomic increment column type |
| Batch with care | LOGGED batch costly; use UNLOGGED for same partition |
7. Implementing Secondary Indexes
| Type | Detail |
| Local secondary (2i) | Per-node — scatter-gather; only with partition key |
| SASI | Deprecated |
| SAI (newer) | Better global secondary indexing |
| Materialized views | Server-maintained denormalized table |
| Best practice | Model query-first; create denormalized table per access pattern |
8. Querying with CQL
Example: CQL Queries
SELECT * FROM events_by_user
WHERE user_id = ? AND event_ts >= ? AND event_ts < ?
LIMIT 100;
INSERT INTO events_by_user (user_id, event_ts, event_id, payload)
VALUES (?, ?, now(), ?) USING TTL 2592000; -- 30 days
Warning: ALLOW FILTERING is a footgun — forces full-table scan. Model query-first instead.
9. Managing Consistency Levels
| Level | Meaning |
| ONE | One replica responds |
| QUORUM | Majority (RF/2 + 1) |
| LOCAL_QUORUM | Majority in local DC (cross-DC tolerant) |
| ALL | All replicas (lowest availability) |
| EACH_QUORUM | Quorum in each DC |
| Rule | R + W > RF for strong consistency |
10. Optimizing Column-Family Queries
| Tip | Detail |
| Always provide partition key | Avoid multi-partition reads |
| Limit clustering range | Targeted slice |
| Use prepared statements | Parser cache + safety |
| Right compaction strategy | STCS, LCS, TWCS per workload |
| Monitor tombstones | Excessive deletes hurt reads |