CockroachDB 24.1 makes requested Read Committed isolation effective
Read Committed reaches general availability with a changed enablement default and an Enterprise requirement. Existing applications can observe different isolation after upgrading even when their SQL stays the same.
An application can request Read Committed while actually running under Serializable. CockroachDB 24.1, released on May 20, changes that situation for Enterprise users. Read Committed reaches general availability, and the cluster setting enabling it now defaults to true. An application whose earlier requests were silently upgraded to Serializable can therefore run with weaker isolation after upgrading, without changing its transaction SQL.
That is the most consequential part of the availability announcement. The new release does not change CockroachDB's ordinary default isolation from Serializable. It changes whether an explicit request for Read Committed takes effect under the documented conditions. The requested mode and the effective mode need to be distinguished when assessing an existing application.
I value CockroachDB's serializable default because it makes a strong consistency choice before application code asks for anything else. Offering Read Committed is useful for migration compatibility, but the upgrade's changed interpretation of an existing request deserves the same attention as a new SQL capability.
The configuration default changes the effective contract
In 23.2, sql.txn.read_committed_isolation.enabled defaulted to false. A transaction requesting Read Committed therefore ran as Serializable unless the feature had been enabled. In 24.1, the setting defaults to true. The release notes identify this as a backward-incompatible change because existing transaction requests can now produce different behavior.
Read Committed also requires a valid Enterprise license in 24.1. Without it, configured Read Committed transactions are upgraded to Serializable. Licensing and the cluster setting both participate in determining the effective mode. The release's statement that the feature is generally available does not mean that every deployment automatically runs every transaction at that level.
The 24.1 Read Committed reference provides the SQL for choosing the mode. The following example assumes a cluster where it is available and illustrates an explicit request for one transaction.
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT 1;
COMMIT;
The constant query demonstrates the syntax, not the changed concurrency contract. An application's interesting behavior occurs when successive statements read shared rows while another transaction commits changes. Merely confirming that BEGIN succeeds does not establish whether the workload previously depended on stronger effective isolation.
The release directs users to the DB Console graph for upgrades of SQL transaction isolation levels. That gives a way to identify whether requests have been running under a stronger level. The question is concrete, since the upgrade can stop performing that substitution for an Enterprise deployment using the new default configuration.
Statement snapshots permit different observations
Read Committed statements see data committed before each statement began. Within one transaction, repeating a query can therefore return a value changed by another transaction. A range of matching rows can also change between statements. These are documented non-repeatable and phantom reads, not evidence that the individual statements ignored committed-state rules.
Serializable offers a different guarantee about the transaction as a whole. Choosing Read Committed allows more interleaving across its statements, which can reduce serialization conflicts but changes what an earlier observation proves. An application that checks a condition and later performs a related write needs to account for concurrent changes between those operations.
Write skew is one documented consequence. Two transactions can read a shared condition and update different rows, with each change appearing acceptable against its own earlier observation. Their combined committed state can violate the condition. Direct conflicts on the same updated row are not required for that anomaly, so evaluating only overlapping writes misses the issue.
The documentation also states that CockroachDB's implementation prevents anomalies within a single statement. That narrows where the weaker behavior applies. It does not extend the same guarantee across an arbitrary sequence of statements in one transaction. The application's transaction boundaries still matter to interpreting the observed state.
I find this distinction more useful than treating the choice as a general speed setting. A migration can need the statement-level behavior its source database provided, while another workload benefits from preserving the stronger default. Those are choices about permissible interleavings and application invariants, with performance consequences attached.
Transaction failure remains possible
The release highlights the absence of RETRY_SERIALIZABLE errors under Read Committed. The versioned reference nevertheless documents transaction aborts from deadlocks and constraint violations. It also identifies rare cases where partial results have already reached the client and the statement cannot retry transparently. Fewer serialization failures do not mean every operation can complete without error handling.
This is a useful qualification to the migration claim. Client-side retry handling for a serializable conflict is one particular responsibility. Deadlock handling and responding to a violated constraint are different responsibilities. An application can remove assumptions tied to the former only while retaining the latter cases in its transaction model.
Locking reads can coordinate access to rows when the weaker level is appropriate. Version 24.1 also allows a shared lock to be reacquired at a higher strength through SELECT FOR UPDATE or a write. That expands coordination options inside the supported model. It does not make the weaker level behave like Serializable for transactions that never request the necessary coordination.
DDL autocommit changes the transaction boundary
Another compatibility option is autocommit_before_ddl. When true, a schema-change statement sent inside an explicit transaction causes that transaction to commit before the schema change executes. The release presents this as useful for tools that struggle with CockroachDB's schema-change restrictions and for schema changes requested around Read Committed transactions.
Committing first is a substantive boundary change. Work performed before the DDL no longer shares a single uncommitted transaction with that schema operation. A tool can gain a supported execution path while losing the grouping it appeared to request. The behavior needs to be understood as an explicit compatibility choice, rather than described as new support for arbitrary transactional DDL.
This setting also shows why accepting existing SQL can involve adapting surrounding behavior. A migration tool may assume that placing commands in one BEGIN block gives them one commit point. Enabling autocommit before DDL changes that assumption deliberately. The setting's value is in making the alternative available and documented.
Procedures become more composable
The release expands the stored-procedure support introduced in 23.2. The 24.1 procedure documentation now supports output and input-output parameters. It also adds nested procedure calls and transaction control through PL/pgSQL statements including COMMIT, ROLLBACK and SET TRANSACTION. These are specific additions to the earlier procedural limitations.
User-defined functions can now call other user-defined functions. PL/pgSQL EXIT and CONTINUE can use conditions. Together these changes make more existing routine structures representable in the database. They should still be evaluated as named capabilities, rather than as a blanket assertion that every PostgreSQL routine now has equivalent behavior.
Output parameters and nested calls address composition and interfaces. Transaction-control support addresses when a routine can complete or abandon work. Those are distinct improvements even when one existing procedure needs both. Their appearance alongside Read Committed reinforces that migration compatibility extends into control flow and transaction boundaries.
Storage work reduces a different source of cost
Version 24.1 also changes Pebble's handling of many range snapshots. The release says most snapshots that previously entered level zero now enter level six directly in the log-structured merge tree. Avoiding their earlier entry point reduces write and read amplification, with effects on node stability and SQL performance. This is a storage-path improvement, independent of the application's chosen isolation level.
The release also offers preview WAL failover for nodes with multiple stores. A store experiencing a disk stall can fail over WAL writing to another store's data directory when configured for that behavior. That concerns local storage availability, while Read Committed concerns transaction observations. General availability of the isolation feature should not be used to imply general availability of this separately labelled preview.
The new SHOW DEFAULT SESSION VARIABLES FOR ROLE command also helps inspect transaction configuration. It exposes the defaults applied to a named user without requiring the administrator to switch to that identity or query a system table. That is useful context when the source of an isolation request is role configuration rather than an explicit BEGIN statement.
May's changes therefore affect several costs through different mechanisms. Storage improvements can reduce repeated internal work. The isolation change alters which concurrency guarantees an explicit request receives. For an existing Enterprise application that already asks for Read Committed, the new enablement default is the part that can change behavior without a corresponding change to its SQL text.