Apache Cassandra Developer Associate study materials
Apache Cassandra Developer Associate study resources

Apache Cassandra Developer Associate common mistakes

Apache Cassandra Developer Associate · Understand the traps and how to avoid them.

Mistake 1

Treating the partition key and clustering columns as interchangeable when writing CREATE TABLE statements, so that a query filtering on a non-key column is assumed to work because the column is 'indexed' or 'important' in the app's mental model.

Candidates coming from relational backgrounds think of primary keys as uniqueness constraints rather than as the routing and on-disk sort mechanism. They do not internalize that the partition key determines the token/ring location and the clustering columns determine row order within a partition, so they design schemas around entity relationships instead of query access patterns.

What to do instead

For every table, write out the exact WHERE clause of each query the application will run, then verify the partition key is fully supplied with equality and clustering columns are restricted in order (equality or a single range on the last one). Practice reading schema output from system_schema.columns to confirm kind (partition_key, clustering, regular) before answering design questions.

Mistake 2

Choosing a partition key with low cardinality or a monotonically increasing value (status, country, timestamp, auto-increment-style ID), then expecting even cluster distribution.

Candidates focus on uniqueness for lookups and forget that the partition key is hashed to a token. Low-cardinality keys create a few enormous partitions; monotonic keys concentrate writes on the last token range and create a hot node. The exam phrases this as 'which key gives even distribution' and candidates pick the most 'natural' business field.

What to do instead

Evaluate candidate keys by cardinality (many distinct values), even access frequency, and bounded partition size (keep partitions well under the ~100 MB guideline and rows under ~100k). Reject any key whose values grow with time or cluster into a small set. For time-series, bucket by a compound key such as (device_id, day_bucket) with the timestamp as a clustering column.

Mistake 3

Confusing consistency level semantics: assuming QUORUM means 'all replicas', that ANY is safe for reads, or that CL applies to the whole cluster rather than per-operation and per-replica-set.

Candidates memorize the acronyms without the arithmetic. They miss that R + W > RF gives strong read-your-writes consistency, that QUORUM is a majority of the replica set (not the cluster), that LOCAL_QUORUM scopes to the local datacenter, and that SERIAL/LOCAL_SERIAL are needed for lightweight-transaction linearizability.

What to do instead

Drill the formula: with RF=3, QUORUM=2, so W=QUORUM and R=QUORUM overlap on at least one replica. Memorize that ANY is write-only and can be lost, ONE is fastest but weakest, and LOCAL_QUORUM is the multi-DC default recommendation. Work through small numeric scenarios until the majority math is automatic.

Mistake 4

Assuming an ALLOW FILTERING query or a secondary index is a general-purpose substitute for a proper table design, and answering performance questions as if these scale like primary-key lookups.

Candidates know the syntax works in cqlsh and conclude it is acceptable. They do not appreciate that ALLOW FILTERING scans partitions (potentially the whole cluster) and that secondary indexes are local per node, so a query on an indexed non-partition column fans out to every node and degrades as the cluster grows.

What to do instead

Treat ALLOW FILTERING as a development-only escape hatch and secondary indexes as suitable only for low-cardinality columns queried alongside a partition key. The correct answer to 'how do I query by this column' is almost always a new denormalized table keyed on that column. Recognize SASI/SAI as index types with their own trade-offs, not magic.

Mistake 5

Writing application code that creates one cluster/session per request, or that ignores prepared statements and builds CQL by string concatenation.

Candidates treat the driver like a JDBC connection pool and do not know that Cluster/Session objects are long-lived, thread-safe, and expensive to build (they hold connection pools and topology metadata). String concatenation also invites injection and forces a full parse and prepare on every call.

What to do instead

Instantiate one Cluster and Session per application (singleton, closed on shutdown), reuse it across threads, and use PreparedStatement with bound values for repeated queries so the driver caches the prepared plan and routes directly to the right coordinator. Configure a load-balancing policy (token-aware) and retry/idempotence settings explicitly.

Mistake 6

Ignoring idempotence and retry semantics: assuming the driver will transparently retry any failed write, or setting a speculative-execution/retry policy without marking statements idempotent.

Candidates assume 'the database handles failures'. In Cassandra a timeout does not mean the write failed - it may have been applied on some replicas - so blind retries can duplicate non-idempotent operations (counters, list appends, application-level side effects). The driver refuses to retry non-idempotent statements by default for exactly this reason.

What to do instead

Mark statements idempotent only when replaying them is safe, prefer idempotent write patterns (upserts with full primary key, LWTs, counters used carefully), and understand that a write timeout requires reading back state rather than assuming failure. Know the difference between read timeout, write timeout, unavailable, and overloaded errors and which retry policy handles each.

Mistake 7

Misreading compaction strategy trade-offs: recommending STCS for a write-once, read-heavy time-series table, or LCS for a write-heavy ingest table, without tying the choice to read/write ratio, tombstone volume, and disk overhead.

Candidates memorize strategy names but not the conditions. They miss that STCS is write-optimized but needs up to ~50% free disk and does not efficiently evict old data, that LCS is read-optimized with higher write amplification, and that TWCS exists specifically for time-series with TTL and is the right answer when data expires by time window.

What to do instead

Build a decision table: STCS for mixed/write-heavy general workloads, LCS for read-heavy with few updates and space to spare, TWCS for time-windowed/TTL data. Also connect strategy to tombstone behavior - gc_grace_seconds, tombstone_failure_threshold, and why dropping data with TTL plus TWCS avoids tombstone pileups.

Mistake 8

Treating repair and hinted handoff as optional or equivalent: assuming replication alone guarantees durability, or that a node returning after downtime is automatically consistent.

Candidates conflate replication factor with consistency. They forget that hints expire (max_hint_window), that a down replica misses writes, and that only anti-entropy repair (or read repair on the read path) reconciles divergence. They also miss that repair must run within gc_grace_seconds to avoid resurrecting deleted data.

What to do instead

Memorize: RF is redundancy, not a consistency guarantee; hints are best-effort and time-bounded; repair is mandatory and should complete within gc_grace_seconds (default 10 days). Know nodetool repair options (full vs incremental), the role of Merkle trees, and why running repair on all nodes regularly is an operational requirement, not a tuning nicety.

Mistake 9

Confusing the roles of memtable, commitlog, and SSTable when reasoning about durability, and answering 'where is my data after a write' or 'what happens on restart' incorrectly.

Candidates learn the write path superficially and assume the memtable is durable or that the commitlog is optional. They miss that writes go to commitlog (for durability) and memtable (for serving), that memtables flush to immutable SSTables, and that reads must consult memtable plus multiple SSTables, which is why compaction matters.

What to do instead

Trace a write end to end: commitlog append, memtable insert, flush to SSTable, compaction merge. Then trace a read: memtable, row cache (if enabled), bloom filter, partition index, SSTables. Use this trace to explain durability (commitlog fsync), read amplification, and why tombstone-heavy SSTables slow reads.

Mistake 10

Diagnosing performance problems by adding nodes or raising consistency levels instead of reading the actual signals: high tombstone counts, large partitions, compaction backlog, GC pauses, or hot nodes shown by tpstats/nodetool.

Candidates default to 'scale out' or 'lower CL' as a reflex, missing that the exam tests whether they can identify the bottleneck from operational output. They do not know which nodetool command reveals what (tablestats, compactionstats, tpstats, status, gossipinfo, describecluster) and therefore cannot map a symptom to a cause.

What to do instead

Memorize a symptom-to-tool map: nodetool tpstats for dropped messages and thread pool saturation, compactionstats for pending compactions, tablestats for partition size, tombstone counts, and SSTable counts, status for ownership and load, gcstats/JVM metrics for GC pressure. Practice proposing a fix tied to the observed metric rather than a generic scaling answer.