May 24, 2022·4 min read·engineeringcassandraguardrailsmemtables

Cassandra 4.1 alpha makes operational policy explicit

Cassandra 4.1 alpha1 exposes guardrails and a memtable implementation API. Both make deployment policy explicit, with different rules for query enforcement and cluster-wide schema compatibility.

Cassandra 4.1 alpha1 gives operators more ways to express the behavior a deployment will permit. Guardrails can reject selected user actions, while a new memtable API lets tables select a named implementation configuration. These changes put decisions into database configuration that previously required external convention or changes deeper in the implementation.

The release metadata dates 4.1-alpha1 to May 24. Its tagged release notes describe the guardrails framework and the alternative memtable API. This is an alpha release, so the useful question is what the new interfaces permit engineers to evaluate. The tag gives that evaluation a specific implementation to inspect.

I like Cassandra when the application requires its distributed design. More explicit operational controls improve that proposition because an application's freedom to submit a query is not a reason for every query shape to be acceptable in a shared deployment.

Guardrails distinguish warning from refusal

The release notes describe soft and hard limits for user actions. Reaching a soft limit produces a client warning. Reaching a hard limit aborts the query. Both also produce a log message and diagnostic event. This gives an operator a choice between exposing an approaching limit and enforcing it.

The listed controls include schema counts, collection sizes, and the number of partition keys selected by IN restrictions. There are also controls for permitted consistency levels and operations such as querying with ALLOW FILTERING. These are different forms of policy. A count threshold limits growth, while an allowed-operation setting can reject an action regardless of its particular size.

The tagged configuration file shows separate table warning and failure thresholds, both disabled by default with -1. A deployment can choose its own values. The following example uses illustrative limits, not defaults or universal sizing recommendations.

tables_warn_threshold: 100
tables_fail_threshold: 150

That separation supports a warning interval before the enforced boundary. It does not make the boundary a capacity estimate derived by Cassandra. The operator supplies the policy, and the framework supplies enforcement and notification. Applications receiving warnings need a way to expose them if those warnings are to affect decisions before a later query fails.

The framework excludes superusers and internal queries. Its scope is regular user queries, so a successful privileged operation does not prove that the same action will succeed for an application role. This is a deliberate distinction in the release notes and matters when demonstrating that a configured limit works.

Some checks cannot attach enforcement to an individual query. The notes identify collection-size detection during compaction and periodic disk-usage monitoring as examples. Those checks emit logs and diagnostic events without aborting the background process. Consequently, the word guardrail does not imply identical rejection behavior for every monitored condition. The enforcement point determines what the database can stop.

The configuration can also change through the org.apache.cassandra.db:type=Guardrails JMX MBean. That makes policy adjustable at runtime. The YAML still provides the persistent configuration, while a runtime change supplies a way to alter the active limits without presenting it as a schema transformation.

A memtable name becomes part of table configuration

The memtable API document in the alpha tag describes named configurations in cassandra.yaml. Each name can specify a class and its parameters, or inherit another configuration. Tables select a name through their memtable property.

That indirection separates the schema's selected name from the node's implementation configuration. The predefined name default remains available even if the YAML does not explicitly define it. Another name can inherit it, creating an alias that initially preserves the default behavior.

memtable:
    configurations:
        application_memtable:
            inherits: default

For an existing table named events in the current keyspace, the corresponding selection is explicit CQL.

ALTER TABLE events WITH memtable = 'application_memtable';

The API document recommends using a separate ALTER statement for a memtable change. Selecting the configuration is a table schema decision and propagates through the cluster. Each node therefore needs to know the name and be able to instantiate the implementation. A node without the definition, without a usable class, or on a pre-4.1 version rejects the schema change.

This creates a clear difference between distributing YAML and changing table configuration. Installing a named configuration on one node does not make the cluster ready to accept it in schema. Conversely, changing the implementation behind an existing name can alter node behavior without choosing a different name in the table definition. The document describes preparing an alias to the default everywhere before changing its implementation one node at a time.

Validation also occurs when a table needs an instance of the configured memtable. The document explicitly says the database validates the class and parameters at that point. Merely placing a configuration block in YAML is therefore not equivalent to exercising the implementation.

The API covers durability responsibilities

A pluggable memtable does more than implement insertion into an in-memory collection. The document requires support for reading rows and partitions, retrieving content for flushing, and tracking memory and statistics. Implementations also need to track commit log spans and support the relevant flush triggers. Shared abstract classes provide parts of that work. The factory also has streaming controls for long-lived memtables that cannot flush as part of streaming.

The factory interface can describe whether writes have their own durability mechanism. A separate option lets an implementation request that writes skip the commit log altogether. The document distinguishes those choices because a durable memtable can still allow commit log records for change data capture or point-in-time restore. Skipping those records is incompatible with those uses.

I find the named configuration approach useful because it makes implementation selection visible in schema without putting all implementation parameters there. Its benefit depends on respecting the cluster-wide agreement about those names. The alpha API provides the configuration and lifecycle contracts that an alternative implementation must satisfy, including the durability decisions that cannot be reduced to a faster insert method.