Chris Collins

Tools · infra

Cassandra lab

A Cassandra data-modelling lab and CQL client: a cqlsh-like console on a built-in Cassandra node (CQL, TTLs, tombstones, SSTables, lightweight transactions), a query-first checker that says which queries a table supports and why, partition sizes and hot partitions, the token ring with vnodes and replica placement, consistency levels with replica responses — and a native-protocol client for your own Cassandra through the gitwebsite app.

Added

Works with

How to use it

Cassandra rewards designing tables around their queries and punishes everything else: a query that does not fit the primary key is refused, or runs only with ALLOW FILTERING and scans the cluster. This page lets you try designs on a Cassandra node simulated in the browser, see where the data lands and what it costs, and then run the same CQL on a real server.

Console

The console works like cqlsh. Type a statement (ending in ; is optional) and press Enter; Shift+Enter adds a line, and a BEGIN BATCH waits for its APPLY BATCH. Results print as cqlsh prints them — the right-aligned table, (3 rows), null, True, timestamps as 2026-01-01 10:00:00.000000+0000 — and errors carry Cassandra’s own messages, such as InvalidRequest: … message="Cannot execute this query as it might involve data filtering …".

  • ↑ ↓ walk the history; Tab completes keywords, tables and columns; the line under the prompt shows the syntax of the statement you are typing.

  • The cqlsh commands work: CONSISTENCY QUORUM, SERIAL CONSISTENCY, PAGING 20 / PAGING OFF (long results stop at --- MORE ---), EXPAND ON (one row per block — handy on a phone), TRACING ON, DESCRIBE KEYSPACES / TABLES / TABLE t, HELP topic, CLEAR.

  • With TRACING ON the built-in node reports each read: how many partitions, whether the memtable and how many SSTables were read, live rows and tombstones scanned. On a real server it prints the session trace from system_traces.events.

  • The built-in node also has NODETOOL FLUSH, NODETOOL COMPACT, NODETOOL TABLESTATS and NODETOOL GETENDPOINTS ks table key (replicas on the Ring tab’s cluster), and ADVANCE 2h, which moves its clock so TTLs expire and tombstones age past gc_grace_seconds without waiting.

  • Examples… loads a scenario into the keyspace lab and runs it (see the table below).

  • Keep data in this browser keeps the built-in node between visits.

What the built-in node runs: keyspaces (SimpleStrategy, NetworkTopologyStrategy), tables with composite partition keys, clustering columns and CLUSTERING ORDER BY, static columns, all the native types, list, set, map, tuple, frozen and user-defined types, counters, default_time_to_live and gc_grace_seconds; INSERT (and INSERT … JSON), UPDATE with collection operations, DELETE of cells, rows, clustering ranges and partitions, USING TTL and USING TIMESTAMP, batches, lightweight transactions (IF NOT EXISTS, IF EXISTS, IF col = …), and SELECT with every restriction Cassandra allows (=, IN, clustering ranges, multi-column (c1, c2) > (…), token() ranges, CONTAINS), ORDER BY, LIMIT, PER PARTITION LIMIT, DISTINCT, GROUP BY, COUNT/MIN/MAX/SUM/AVG, TTL(), WRITETIME(), token(), SELECT JSON, now(), uuid(), toTimestamp() and friends. Storage-attached indexes (CREATE INDEX … USING 'sai') let a query restrict an indexed column. Writes are last-write-wins cells with timestamps; reads merge the memtable and every SSTable holding the partition.

Model

Pick a table (yours, an example’s, or — when you are connected — one read from your server’s system_schema):

  • The primary key’s two jobs: the partition key (red) decides which nodes store a row; the clustering columns (blue) sort rows inside a partition.

  • Partition size estimate: rows per partition and average value sizes give the cells per partition and bytes per partition with the formula from Carpenter and Hewitt, Cassandra: The Definitive Guide (ch. 5) — Nv = Nr × (Nc − Npk − Ns) + Ns and Ps = Σ pk + Σ static + Nr × Σ (clustering + regular) + 8 × Nv — and warns past the usual guidance of about 100 MB and 100,000 cells per partition.

  • Partitions in the built-in node: Add sample rows writes rows with a Zipf skew so you can watch hot partitions appear; the list shows each partition’s rows, size and tombstones, flags partitions over three times the mean, and gives the busiest node’s share on the Ring tab’s cluster. Click a partition to see it on the ring.

  • Query-first checker: one SELECT per line (? for values). Each is checked with Cassandra’s rules and gets a verdict — a single-partition read, an IN fan-out, a token-range scan, an index scatter-gather, a filtered scan, or a refusal with the exact error — with the reason (which restriction breaks the rules) and what to do instead: a table keyed for that query, or an index. The rules are those of Cassandra 5, checked against a real server.

Storage

The memtable and the SSTables of one table, newest first, with each partition fragment’s live rows and tombstones; Flush, Compact (a major compaction) and clock buttons (+1 h, +1 day, +10 days — gc_grace_seconds is 10 days by default). Compaction drops data shadowed by newer writes and tombstones, and purges tombstones — including expired TTL cells, which become tombstones — only once gc_grace_seconds has passed. A chart follows tombstones and live rows after each step. Reads over more than 1,000 tombstones print Cassandra’s warning (tombstone_warn_threshold); 100,000 fail the read (tombstone_failure_threshold). Writing a whole non-frozen collection also writes a tombstone for its old contents, and the console says so.

Ring

Nodes, data centres, replication factor, num_tokens (vnodes, 1–256) and token allocation (random as before Cassandra 4.0, or evenly spread as the allocator does). The ring colours each node’s token ranges; type a partition key to see its Murmur3 token and its replicas (NetworkTopologyStrategy picks RF distinct nodes per DC, preferring new racks; SimpleStrategy the next nodes clockwise). Choose a table to plot its partitions at their tokens (dot size: partition size). The ownership bars show how evenly the ranges are spread — more vnodes, more even. Tokens are computed exactly as Cassandra’s Murmur3Partitioner does (MurmurHash3 x64_128 with Cassandra’s sign-extension quirk; composite keys are CompositeType-encoded), and tested against tokens from a real server.

Consistency

A coordinator, the replicas of one partition (RF per DC, up to three DCs) and a consistency level for a read or a write. Send another request animates the requests and replies (latencies are drawn from a seeded log-normal around the median you set, plus a cross-DC delay); the coordinator answers once enough replicas have replied. Click replicas to take them down: the result shows success, Unavailable (too few replicas alive — checked before anything is sent) or a timeout. It also says how many replicas the level needs (QUORUM = ⌊ΣRF/2⌋ + 1, LOCAL_QUORUM = ⌊RFlocal/2⌋ + 1, EACH_QUORUM a quorum in every DC), how many may be lost, and a read/write matrix of which combinations satisfy R + W > RF. Full screen (⛶, or F) works on the Ring and Consistency diagrams and on the console.

Docs and History

Docs covers the CQL statements, the WHERE rules, ALLOW FILTERING, TTL, collections, counters, lightweight transactions, and the concepts behind them (partition keys, clustering, query-first modelling, tombstones, memtables and SSTables, consistency, replication, hints and read repair, paging, the native protocol), with examples you can Try in a fresh built-in node or run in the console; each page links to the Apache Cassandra documentation. History keeps statements per connection, only in this browser; anything with a password is never saved.

Connecting to a real Cassandra

Choose Real server. The page speaks Cassandra’s native protocol itself — version 5 with its checksummed segments (CRC24 headers, CRC32 payloads), falling back to version 4 — with PasswordAuthenticator (SASL PLAIN), paging, warnings and tracing. Browsers cannot open TCP connections, so the bytes travel through:

The gitwebsite app. If it is running on your computer, keep ⚡ gitwebsite app, enter host:port (for example 127.0.0.1:9042) and Connect. The app’s TCP relay connects to Cassandra; the first time, the app asks you to allow that target (it must be on its TCP allow-list).

A WebSocket bridge when the app is not running, for example with websockify, listening on this machine only:

websockify 127.0.0.1:9043 127.0.0.1:9042

and connect to ws://localhost:9043. Anyone who can reach a bridge can reach your database: keep it on 127.0.0.1 and stop it when you are done.

On a real server DROP, TRUNCATE, ALTER, role changes, DELETE of whole partitions or ranges, and batches of deletes ask before they run. The username and password stay in memory unless you tick Remember (then they are kept in this browser’s storage, readable by anyone using it); they never go into links or history. Show frames prints each protocol frame (opcode, stream, length and the first bytes). The Model tab reads your server’s schema, never its data.

Limits

  • The built-in node is one node: consistency levels are accepted but every request succeeds; the Consistency tab models a cluster instead. There is no commit log, no real compaction strategy (Compact is a major compaction), no hinted handoff or repair, and its "SSTables" are in memory.

  • Not built in: materialized views, user-defined functions and aggregates, triggers, roles and permissions, CAST, duration arithmetic, vector search, LIKE without an index, ALLOW FILTERING statistics beyond the trace line. Secondary indexes behave as SAI for equality and ranges without modelling their cost per node.

  • Non-frozen collections are stored whole (element tombstones are counted when you overwrite one, not stored per element); uuid ordering follows Cassandra’s UUIDType (version, then time for version 1, then bytes).

  • Partition sizes are uncompressed estimates. Latencies in the Consistency tab are a model, not measurements.

  • The native-protocol client does not compress frames (LZ4/Snappy), use TLS, or follow EVENT pushes; it decodes all native types, collections, tuples, user-defined types and vectors.

  • The built-in node is tested against a real Cassandra 5.0: the same scripts must print the same rows and the same error messages (tests/tools/cassandra-live.test.js).

Linking to an example

Links can be written by hand. Add the tab after #: console, model, storage, ring, consistency, docs or history. A link never connects to a server and never carries a password.

Parameter Meaning Example

example

Load a scenario below into the built-in node (and open its tab)

example=hot-partition

cql

Statements to run in the built-in node (filled in, not run, for a real server); %0A between lines

cql=SELECT%20*%20FROM%20system.local

doc

Open a reference page

doc=WHERE%20rules#docs

q

A search in the Docs tab

q=tombstone#docs

conn

builtin or server

conn=server

target

Server host:port for the gitwebsite app

target=127.0.0.1:9042

cl

Console consistency level

cl=LOCAL_QUORUM

nodes, dcs, rf, vnodes, key

The Ring tab’s cluster and key

nodes=8&vnodes=4&key=jsmith#ring

level, write, down

The Consistency tab: level, true for a write, down replicas (indexes from 0)

level=QUORUM&write=true#consistency

table

The table the Model and Storage tabs show

table=lab.readings#model

Presets for example=:

example= Shows

iot-buckets

Sensor readings partitioned by (sensor, day), newest first, with the query checker (open)

hot-partition

Events keyed by type: a skewed key makes one huge, hot partition (open)

users-by-email

Two tables for two queries, kept in step with a logged batch (open)

chat-messages

Messages by (room, month), timeuuid DESC, a static topic (open)

queue-antipattern

A table used as a queue: 1,499 tombstones in front of one live row (open)

ttl-sessions

Expiring sessions, gc_grace_seconds and compaction (open)

lwt-signup

Unique usernames with IF NOT EXISTS (open)

filtering

The same question asked with ALLOW FILTERING and of a table built for it (open)

quorum

RF 3 with a replica down: QUORUM still works (open)

Runs entirely in your browser — network requests go only to the services named on this page.