Skip to main content
The releases on this page are testing releases, not supported or intended for production environments. The new features and bug fixes noted on this page may not yet be documented across CockroachDB’s documentation.
  • CockroachDB self-hosted: All v26.4 testing binaries and Docker images are available for download.
  • CockroachDB Advanced: v26.4 testing releases are not yet available.
  • CockroachDB Standard and Basic: v26.4 testing releases are not available.
When v26.4 becomes Generally Available (GA), a new v26.4.0 section on this page will describe key features and additional upgrade considerations.
CockroachDB v26.4 is in active development, and the following are intended for testing and experimentation only, and are not qualified for production environments or eligible for support or uptime SLA commitments. When CockroachDB v26.4 is Generally Available (GA), production releases will also be announced on this page.
  • For details about release types, naming, and licensing, refer to the page.
  • Be sure to also review the .
  • After downloading a supported CockroachDB binary, learn how to or .
Get future release notes emailed to you:

v26.4.0-alpha.1

Release Date: September 9, 2026

Downloads

CockroachDB v26.4.0-alpha.1 is a testing release. Testing releases are intended for testing and experimentation only, and are not qualified for production environments and not eligible for support or uptime SLA commitments.
Experimental downloads are not qualified for production use and not eligible for support or uptime SLA commitments, whether they are for testing releases or production releases.
Operating SystemArchitectureFull executableSQL-only executable
LinuxIntelcockroach-v26.4.0-alpha.1.linux-amd64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.1.linux-amd64.tgz
(SHA256)
ARMcockroach-v26.4.0-alpha.1.linux-arm64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.1.linux-arm64.tgz
(SHA256)
Mac
(Experimental)
Intelcockroach-v26.4.0-alpha.1.darwin-10.9-amd64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.1.darwin-10.9-amd64.tgz
(SHA256)
ARMcockroach-v26.4.0-alpha.1.darwin-11.0-arm64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.1.darwin-11.0-arm64.tgz
(SHA256)
Windows
(Experimental)
Intelcockroach-v26.4.0-alpha.1.windows-6.2-amd64.zip
(SHA256)
cockroach-sql-v26.4.0-alpha.1.windows-6.2-amd64.zip
(SHA256)

Docker image

Multi-platform images include support for both Intel and ARM. Multi-platform images do not take up additional space on your Docker host. Within the multi-platform image, both Intel and ARM images are available for testing. To download the Docker image:

Backward-incompatible changes

  • ALTER FUNCTION ... RENAME and ALTER PROCEDURE ... RENAME now require the CREATE privilege on the schema containing the object, matching PostgreSQL behavior. Renames in the public schema are unaffected in the default configuration because all users have CREATE on that schema.
  • Fixed a security issue with SAN-required client certificate authentication (security.client_cert.san_required.enabled): if an HBA certificate rule omitted the map option, CockroachDB could accept a client certificate without verifying it was bound to the requested non-privileged SQL user. After this change, non-privileged users must be explicitly bound to the certificate via an identity map (map on the certificate HBA rule configured with server.identity_map.configuration) or an exact subject DN (the SUBJECT role option); otherwise, the login is rejected. If you rely on SAN-required client cert auth, configure one of these bindings before upgrading.
  • GROUP BY and a window’s ORDER BY or PARTITION BY clause no longer accept an expression of a type that has no comparison operators, namely refcursor, jsonpath, and the trigger pseudo-type. Such a query now returns the same “could not identify an ordering/equality operator” error that PostgreSQL returns, and that the equivalent statement-level ORDER BY already returned. A query that relied on this must cast the expression to a comparable type (for example GROUP BY c::STRING) or drop it from the clause.

Security updates

  • Security: Fixed an issue where a tenant-scoped client certificate could bypass tenant-scope checks and gain cluster-wide RPC access if its subject distinguished name (DN) matched the configured root or node DN. Fixed a related issue where certificate authentication could bypass the disallow-root-login policy when the certificate DN or subject alternative name (SAN) matched a root identity.
  • Fixed a security issue by rejecting invalid transaction commit requests from secondary tenants that could have allowed an authenticated tenant to exceed its granted capabilities.
  • When SSO/OIDC authentication fails because the user does not exist in CockroachDB or lacks DB Console login privileges, CockroachDB now emits a structured ClientAuthenticationFailed event to the SESSIONS log channel with reason USER_NOT_FOUND or LOGIN_DISABLED. This enables production alerting on SSO provisioning gaps without exposing user-existence details to unauthenticated clients.
  • Fixed a security issue where a non-admin user could use a LEAKPROOF user-defined function to bypass row-level security (RLS). Setting LEAKPROOF via CREATE FUNCTION, CREATE OR REPLACE FUNCTION, or ALTER FUNCTION now requires membership in the admin role; NOT LEAKPROOF is unchanged. Existing LEAKPROOF functions are not modified. On upgrade, CockroachDB logs warnings for any existing LEAKPROOF UDFs owned by non-admin users so operators can review and, if needed, remove the LEAKPROOF designation.
  • SASL OAUTHBEARER authentication now returns an RFC 7628–compliant SASL error response when token validation fails. In this case the broker responds with an AuthenticationSASLContinue message containing a JSON error body, allowing compliant clients to detect an invalid_token condition and (when provided) the required scope to request. Invalid SASL framing (e.g., unsupported channel binding data or a non-empty authzid) is unchanged and continues to fail the connection without an OAuth error response.
  • The OIDC authorization-code authentication flow now supports PKCE (Proof Key for Code Exchange). PKCE can be required by some identity providers and helps protect against authorization-code interception. It is disabled by default and can be enabled with the server.oidc_authentication.pkce.enabled cluster setting.
  • Fixed a DB Console security issue where the login endpoints returned a distinct error message when an account’s password had expired, which could allow username enumeration. The login endpoints now return a uniform error for all authentication failures.
  • The DB Console login endpoints now take a comparable amount of time for all failed logins, whether the user does not exist, has no password, or has an expired password, preventing an unauthenticated attacker from enumerating valid usernames by measuring response latency. SQL clients now receive the same generic authentication error for an expired password as for a wrong one.
  • String-valued group claims for JWT, OIDC, and OAUTHBEARER authorization are now split on commas only when synchronizing SQL role memberships. Identity providers that convey multiple groups should return a JSON array.
  • CockroachDB no longer grants reserved or privileged SQL roles (such as admin) through JWT, OIDC, OAUTHBEARER, or LDAP group-based authorization, even when an identity-provider group is named after such a role.
  • The OIDC JWT authentication endpoint now sets Cache-Control: no-store and Pragma: no-cache on its responses so intermediaries do not cache the returned SQL credential bundle.
  • Improved synchronization of SQL role memberships from external identity providers (OIDC, JWT, LDAP, and OAUTHBEARER). CockroachDB now reconciles only a user’s direct role grants, preventing unintended removal of roles inherited through parent roles. Security update: OIDC logins are now denied without modifying role memberships if the groups claim cannot be found in the ID token, access token, or userinfo response (for example, due to a transient identity provider failure). If the identity provider explicitly returns an empty groups list, CockroachDB will continue to revoke roles and deny the login.
  • When a TLS cipher-suite allowlist is configured via the tls-cipher-suites flag, a connection to the HTTP interface that negotiates a disallowed cipher is now rejected during the TLS handshake (surfaced to the client as a TLS handshake failure) instead of being closed immediately afterward. This also prevents a slow or stalled TLS handshake on the HTTP port from delaying other incoming HTTP connections.
  • CREATE LOGICAL REPLICATION STREAM now requires USAGE on the external connection named as the source. Non-admin users must be granted USAGE on that connection; admins are unaffected.
  • Fixed an information disclosure issue in the /api/v2/grants/databases/ and /api/v2/grants/tables/ HTTP API endpoints where an authenticated SQL user could enumerate database, schema, and table names for objects they did not have privileges on. These endpoints now return 404 for objects the user cannot access.
  • Fixed a bug where the loss-of-quorum recovery plan file (staged.bin) was written unencrypted to disk even on stores with encryption-at-rest enabled, potentially exposing range start keys containing fragments of user data. The plan file is now encrypted like the rest of the store’s data when EAR is enabled.
  • Creating or altering a changefeed that uses an external connection (as a sink or for a Confluent schema registry) now requires the USAGE privilege on that external connection. This also applies to users with the CONTROLCHANGEFEED role option.
  • EXPORT now requires the USAGE privilege on an external connection named in its destination URI.
  • ALTER BACKUP now checks privileges on its collection URI, requiring the USAGE privilege when that URI names an external connection.
  • Starting or restarting Physical Cluster Replication (PCR) from an external connection now requires the USAGE privilege on that external connection.
  • CREATE LOGICALLY REPLICATED TABLES ... WITH BIDIRECTIONAL ON now reports a missing USAGE privilege on the reverse stream’s external connection when the statement is run, instead of allowing the job to start and fail later.
  • The internal built-in crdb_internal.backup_compaction now requires the BACKUP system privilege, plus the same destination privileges as BACKUP (for example, EXTERNALIOIMPLICITACCESS for implicitly authenticated destinations and USAGE on external connections). These checks apply only to direct invocation of the built-in; compactions run via scheduled backups are unchanged.
  • crdb_internal.backup_compaction now requires the USAGE privilege on an external connection named in a KMS URI, in addition to the privileges its destination requires. Compactions triggered automatically by a backup schedule are unaffected.
  • BACKUP, ALTER BACKUP, SHOW BACKUP and RESTORE now require the USAGE privilege on an external connection named in a KMS URI. Existing backup schedules whose owner lacks USAGE on a KMS external connection will fail until the grant is made. A schedule created with on_execution_failure = 'pause' must also be resumed with RESUME SCHEDULE once the grant is in place.
  • The cluster.secret, enterprise.license, and cloudstorage.http.custom_ca cluster settings are now marked sensitive. Their values are redacted for users without the MODIFYCLUSTERSETTING privilege when server.redact_sensitive_settings.enabled is set, and are suppressed from diagnostics artifacts. The sql.override.allow_unsafe_internals.enabled setting is no longer marked sensitive.
  • The events.json file in debug zips no longer contains statement placeholder values, which can carry sensitive data such as passwords or sensitive cluster setting values bound via prepared statements. The value recorded for ALTER TENANT ... SET CLUSTER SETTING events is now also hidden there, matching regular setting-change events.
  • The settings.json file in debug zips and the DB Console settings page no longer show the values of sensitive cluster settings (such as authentication secrets), even for users with the MODIFYCLUSTERSETTING privilege and even in debug zips collected without the --redact flag. Sensitive values are replaced with ‘<redacted>’. Privileged users can still read these values with SHOW CLUSTER SETTING.
  • The set_cluster_setting and set_tenant_cluster_setting events written to system.eventlog no longer record the values of sensitive cluster settings (such as authentication secrets). The event’s value field contains <redacted> instead; resets are still recorded as DEFAULT.
  • Unredacted debug zips no longer contain the values of sensitive cluster settings (such as authentication secrets). This covers the system.settings, system.tenant_settings, crdb_internal.cluster_settings and system.eventlog dumps. Values for settings not known to the current version are conservatively redacted as well. The session and query dumps now hide SQL constants in statement text, so that a setting value typed in a session is no longer carried in an unredacted zip. Debug zips collected without --redact no longer contain the connection details of external connections or the execution arguments of scheduled jobs, both of which can hold cloud storage credentials.
  • CREATE ROLE and ALTER ROLE statements that supply the password via a bound placeholder (for example, a prepared statement executed with arguments, the typical driver behavior) no longer record the raw password in the system event log or SQL logs; the recorded placeholder value is *****, matching the existing treatment of password literals. Debug zips collected without --redact also scrub bound placeholder values of historical role-change events from the event log dump and from log files.
  • The error reported when the cloudstorage.http.custom_ca cluster setting holds an unparsable certificate no longer includes the setting’s value.
  • Debug zips collected without --redact and the output of cockroach debug merge-logs no longer include log entries that reveal the values of sensitive cluster settings (such as authentication secrets). Affected entries are redacted in place when possible (requires redactable logs, the default) and replaced with a tombstone otherwise. Entries that mention a sensitive setting without containing its value are scrubbed as well. When any such scrubbing occurs, the debug zip contains a sensitive_settings_warning.txt file describing what was removed.
  • Fixed redaction of connection URIs that can embed credentials in the statement text of CREATE CHANGEFEED ... AS SELECT, CREATE SCHEDULE FOR CHANGEFEED, CREATE LOGICAL REPLICATION STREAM, and CREATE LOGICALLY REPLICATED. Such URIs now render as '*****' in contexts like SHOW CREATE SCHEDULE.
  • Statements that reference external URIs, connection strings, or encryption passphrases that can embed credentials - such as BACKUP, RESTORE, IMPORT, EXPORT, changefeed, EXTERNAL CONNECTION, and replication statements - are now treated as possibly carrying a secret, so their constants, bound placeholder values, and recorded errors are kept out of diagnostics artifacts (e.g. SHOW QUERIES, recorded SQL event details, and statement statistics). The full error is still returned to the client.
  • Statement diagnostic bundles now redact cleartext passwords and credential-bearing URIs in formatted statements by default (for example, in BACKUP, RESTORE, IMPORT, EXPORT, and CREATE ROLE ... WITH PASSWORD).
  • Security improvement for replication statements: the source connection URI in CREATE VIRTUAL CLUSTER ... FROM REPLICATION and ALTER VIRTUAL CLUSTER ... START REPLICATION is now redacted by default in reformatted statement output, while job descriptions continue to display a sanitized URI.
  • Security improvement for IMPORT ... AVRO: the schema_uri option is now redacted in formatted SQL output, and any secret query parameters in schema_uri are sanitized in IMPORT job descriptions (e.g., SHOW JOBS) to prevent leaking embedded cloud credentials.

General changes

  • CREATE CHANGEFEED now supports the create_kafka_topics option to control Kafka topic creation: broker_auto (default) relies on the Kafka cluster to auto-create topics, explicit creates topics using the Kafka Admin API, and off disables topic creation.
  • The admission.cpu_time_tokens.per_tenant.* metrics have been removed. Use admission.cpu_time_tokens.{admitted_count,wait_time_nanos, tokens_used,tokens_returned}, labeled by (tenant_id, group_id), instead.
  • The no-linger sink for changefeeds (the default for the kafka, webhook, and pubsub v2 sinks) no longer requires Frequency when Messages or Bytes is set. The no-linger sink interprets the Flush.Frequency sink config option as a minimum linger; a batch is held until its oldest event is at least Frequency old, coalescing events into fewer, larger requests at the cost of latency, for example kafka_sink_config='{"Flush": {"Frequency": "1s"}}'. Leave it unset for the lowest latency.
  • Changefeeds using format=avro with a schema registry now support an avro_mode option. The default (avro_mode=write) preserves existing behavior by registering schemas with the registry. Setting avro_mode=read makes schema-registry interaction read-only: the changefeed performs no registry writes and instead looks up an already-registered schema ID, failing if no matching schema is found.
  • Sinkless changefeeds now accept the mvcc_ordered option to emit rows in non-decreasing updated-timestamp order.
  • Removed the changefeed.new_kafka_sink.enabled cluster setting. The Kafka changefeed sink now always uses the franz-go implementation.

Enterprise edition changes

  • Added support for automatic user provisioning for clients authenticating with SASL OAUTHBEARER When the cluster setting security.provisioning.oauth.enabled is enabled, a successful OAUTHBEARER authentication for a non-existent SQL user creates that user. The created role is marked with the PROVISIONSRC role option set to oauth:<issuer> to identify the token issuer as the provisioning source.
  • Avro changefeeds can now resolve schema IDs from a Confluent-compatible schema registry without writing to it. Set avro_mode='read' to use read-only (GET) requests to resolve existing subjects. The new avro_schemas option lets you override subject names and select the registered version to use in read mode: latest (default), latest_compatible, or pin(<n>). Subject-name overrides also apply in the default write mode.
  • CREATE LOGICAL REPLICATION STREAM and CREATE LOGICALLY REPLICATED TABLE now accept a DLQ = <schema> (or <database>.<schema>) option with MODE = 'transactional'. When set, source transactions that fail to apply with a DLQ-eligible error, such as a unique constraint violation, are recorded in per-job dead letter queue tables under the specified schema and replication continues past them, instead of pausing the job.
  • Avro changefeeds can now set avro_resolved_subject to store resolved-timestamp schemas in a dedicated Schema Registry subject. Read-only Avro mode now supports resolved timestamps when this option is set.

SQL language changes

  • Updated EXPLAIN ANALYZE to show the body plan for user-defined functions (UDFs) and stored procedures, including per-node execution statistics, invocation counts, and plan variants based on routine arguments. Updated EXPLAIN (OPT, ...) and statement bundles to show routine bodies under the routine node. Output is truncated with a note if more than 100 plan variants are encountered in the same statement.
  • Added support for ALTER DOMAIN ... DROP CONSTRAINT.
  • Fixed EXPLAIN ANALYZE to include KV read metrics from statements executed inside routine bodies (for example, PL/pgSQL), ensuring top-level statistics (such as rows decoded from KV) reflect the full work performed and are reported consistently.
  • Added a query_tags column to crdb_internal.node_active_session_history and crdb_internal.cluster_active_session_history to expose sqlcommenter query tags associated with each sampled statement, as a JSONB array of {name, value} objects. Populating this column requires sql.sqlcommenter.enabled and obs.ash.enrichment.query_tags.enabled (disabled by default).
  • Added a new STATEMENTHINTS privilege to control access to the statement-hints built-ins (e.g., crdb_rewrite_inline_hints, crdb_delete_statement_hints, crdb_enable_statement_hints, crdb_set_session_variable_hint, crdb_pin_plan_gist, crdb_pin_plan_gram) without requiring REPAIRCLUSTER. This privilege can be granted at the system level or per database; REPAIRCLUSTER continues to grant access for backward compatibility.
  • The crdb_delete_statement_hints and crdb_enable_statement_hints built-ins now accept an optional database argument along with a hint row ID, allowing users with database-scoped STATEMENTHINTS to manage individual statement hints.
  • Added EXPLAIN ANALYZE execution details for statements in the body of PL/pgSQL subroutines.
  • The optimizer_use_routine_decorrelation_fix session setting is now on by default in 26.3+.
  • Added the optimizer_use_routine_decorrelation_fix session setting (enabled by default) to improve query planning for user-defined functions (UDFs) and stored procedures that reference routine parameters or PL/pgSQL variables. With this setting enabled, the optimizer defers certain rewrites until the routine is inlined or executed, which can prevent parameter-dependent filters from being moved in ways that lead to less selective scans (e.g., full table scans instead of constrained access paths).
  • EXPLAIN EXECUTE is now supported. It shows the query plan for a prepared statement with the specified parameters without executing it, matching EXPLAIN behavior for non-prepared statements.
  • PL/pgSQL routines can now create or alter an object and reference it in a subsequent statement, even when the statements are nested within the same IF, loop, or block.
  • Index recommendations can now suggest replacing an existing unique index with a new index that extends it, allowing you to collapse redundant indexes into a single index when doing so preserves uniqueness.
  • Row-level TTL now finds expired rows through a secondary index on the expiration column automatically, instead of always scanning the primary index. Because expired rows are contiguous in such an index, this can reduce the cost of TTL jobs on large tables where only a small fraction of rows is expired at any time. The job uses such an index only when the estimated fraction of expired rows is below the new sql.ttl.index_scan.auto_max_expired_fraction cluster setting (default 0.05); set it to 0 to disable the index-scan path or 1 to always use a usable index.
  • Foreign key referential actions (for example, ON DELETE CASCADE and ON UPDATE CASCADE) now run with the privileges of the referencing table owner (including any triggered triggers and check constraints), rather than the user performing the mutation. This matches PostgreSQL behavior and can reduce the privileges required for users who modify referenced tables. The row-level TTL job now also runs as the table owner instead of the node user.
  • Row-level TTL jobs now run their SELECT and DELETE operations as the TTL table’s owner instead of an internal superuser. As a result, any user-defined code invoked by TTL deletes (for example, DELETE triggers) runs with the table owner’s privileges and sees current_user as the table owner. Row-level TTL still deletes expired rows even when FORCE ROW LEVEL SECURITY would hide them from the owner, or when the owner lacks EXECUTE privileges on referenced functions.
  • Schema owners can now DROP FUNCTION and DROP PROCEDURE objects in their schema, matching PostgreSQL behavior.
  • Added the admission.kv.cpu_time_token_filler.dampening.enabled cluster setting, which lets operators disable runnable-goroutine-based dampening in the KV CPU time token filler.
  • CREATE / ALTER / DROP / SHOW RESOURCE GROUP return an unimplemented error at plan time by default. Setting sql.experimental_resource_groups.enabled = true bypasses this and re-enables the previous behavior for internal testing.
  • CockroachDB now supports statement-level (FOR EACH STATEMENT) triggers for INSERT, UPDATE, DELETE, and UPSERT on tables. A statement-level trigger fires its trigger function once per statement, before or after the mutation, even if the statement affects no rows.
  • Added support for the ST_BuildArea and ST_ConcaveHull geospatial functions.
  • Added the disallow_ddl_in_explicit_transactions session setting. When enabled, running DDL in an explicit transaction returns an error instead of auto-committing prior statements, helping prevent DML from being silently committed and therefore not rollable back. This setting is disabled by default and can be enabled for all users with ALTER ROLE ALL SET.
  • ALTER TABLE ... ALTER COLUMN ... SET DATA TYPE operations that require rewriting on-disk data are now supported when the column is part of a secondary index; CockroachDB rebuilds the affected indexes to use the new column type. Altering the type of a column that is part of an inverted index is still not supported.
  • The REFERENCING clause for CREATE TRIGGER is now supported. It allows AFTER triggers to reference the complete set of rows inserted, updated, or deleted by the triggering statement as relations (known as transition tables) inside the trigger function body, using the aliases given by REFERENCING OLD TABLE AS and REFERENCING NEW TABLE AS.
  • GRANT and REVOKE statements that accidentally omit the SYSTEM keyword (e.g. GRANT VIEWACTIVITY TO user) now include a hint in the error message directing the user to the correct GRANT SYSTEM <privilege> TO ... syntax.
  • Added the session setting optimizer_use_histograms_for_multi_span_const_columns, which controls whether the optimizer uses histogram statistics for columns constrained to a single constant value in every span of a multi-span index constraint, even when an earlier index column is not constrained to a single value. The setting defaults to false.
  • For statements inside UDF and stored procedure bodies, EXPLAIN ANALYZE now reports per-operator execution statistics aggregated across all routine invocations, shown as an average with minimum and maximum values.
  • The cpu_sql_nanos, cpu_sql_nanos_sum, and cpu_sql_nanos_sum_sq columns of the information_schema.crdb_statement_statistics and information_schema.crdb_transaction_statistics views are deprecated. They will be replaced by a column reporting the always-on SQL CPU measurement (recorded on every execution) in a future release, and remain populated until then.
  • EXPLAIN ANALYZE now displays plans and invocation counts for inlined routine-body statements and user-defined function calls, which previously could execute without appearing in the output.
  • The transaction_rows_read_err guardrail now accounts for rows read by earlier statements in the same explicit transaction when limiting how many rows a later statement may read. This causes a transaction that will exceed the limit to fail sooner, avoiding wasted work, rather than allowing each statement to read up to the full limit before erroring.
  • Adding a VIRTUAL computed column no longer scans the table to validate the expression against existing rows by default. If the expression is invalid (for example, it can produce a value too large for the declared type), the error is now returned when the column is read. To enable validation during ADD COLUMN, set sql.schema.validate_virtual_computed_columns.enabled (disabled by default).
  • The ALTER TABLE ... AUDIT SET syntax is now GA. The previous EXPERIMENTAL_AUDIT keyword is deprecated and will be removed in a future release.
  • Added two new information_schema views, information_schema.crdb_statement_execution_insights and information_schema.crdb_transaction_execution_insights, which expose persisted user-workload statement and transaction execution insights with a stable schema.
  • EXPLAIN ANALYZE (VERBOSE) now reports estimated max memory allocated and estimated max SQL temp disk usage used to store the result of a subquery operator.
  • EXPLAIN ANALYZE (VERBOSE) now reports estimated max memory allocated and estimated max SQL temp disk usage for the buffer, apply join, and recursive CTE operators.
  • CREATE TABLE with storage parameters other than the row-level TTL family is now handled by the declarative schema changer.
  • CREATE TABLE with row-level TTL storage parameters is now handled by the declarative schema changer.
  • When sql.procedures.plpgsql.late_binding.enabled is enabled, a PL/pgSQL exception handler can now reference objects created or altered by DDL earlier in the same handler. In addition, exception handlers that never execute are no longer name-resolved at CALL time.
  • The owner of a schema can now execute DROP TYPE and DROP DOMAIN on types and domains in that schema without owning the type itself, matching PostgreSQL. ALTER TYPE, ALTER DOMAIN, and COMMENT ON TYPE still require ownership of the type.
  • CockroachDB now supports ALTER SCHEMA ... RENAME TO in the declarative schema changer. Renaming a schema requires ownership of the schema, and is rejected if any object in the schema is referenced by name by a view, routine, or trigger.
  • The information_schema.domains, domain_constraints, domain_udt_usage, and column_domain_usage tables are now populated. SHOW TYPES now lists domain types in addition to enums and composite types, and includes a new category column identifying the kind of each type. information_schema.columns now reports domain-typed columns using their base type for data_type and udt_name while identifying the domain in the domain_catalog, domain_schema, and domain_name columns.
  • The information_schema.crdb_statement_statistics and information_schema.crdb_transaction_statistics views now include sql_cpu_time_nanos_sum and sql_cpu_time_nanos_sum_sq, which report the sum and sum of squares of the always-on SQL CPU time recorded for each execution.
  • Added the sql.stats.automatic_node_worker_count cluster setting to control how many concurrent automatic table statistics collection jobs a single node can initiate. Cluster-wide concurrency limits for automatic statistics collection are still enforced.
  • ALTER TYPE ... DROP VALUE now supports the IF EXISTS clause, allowing an enum value to be dropped only if it exists and preventing an error when the value is not present.
  • Added support for ALTER DOMAIN ... VALIDATE CONSTRAINT, which validates existing rows against the constraint, fails if any rows violate it, and marks the constraint as validated on success.
  • Added the uuidv4() built-in function as an alias for gen_random_uuid().
  • The information_schema.crdb_index_usage_statistics view now includes total_writes and last_write.
  • CockroachDB now supports the SQL/JSON json_array() and json_object() constructor functions from the SQL standard (as of PostgreSQL 16), including the { NULL | ABSENT } ON NULL, { WITH | WITHOUT } UNIQUE [ KEYS ], and RETURNING clauses. For example, json_object('a' VALUE 1, 'b' VALUE 2) returns {"a": 1, "b": 2}.
  • CREATE DOMAIN and ALTER DOMAIN now reject domain constraint names that match the reserved internal pattern crdb_internal_constraint_<id>_name_placeholder.
  • The information_schema.crdb_index_usage_statistics view now includes database_name, schema_name, table_name, and index_name columns (in addition to table_id and index_id), allowing index usage statistics to be queried by object name without joining crdb_internal views.
  • IMPORT INTO now supports WITH execution_locality = '...' to constrain import execution to SQL instances that match a given locality filter (for example, region=us-east1). This can reduce cross-region traffic and help avoid cloud authentication failures from out-of-region nodes. An empty value leaves the import unconstrained.
  • Added the information_schema.crdb_indexes view to simplify querying per-index metadata. The view lists each index’s ID, name, owning table and database, key span, and index type (primary, secondary, unique, or inverted), providing stable schema-introspection columns that previously required joining multiple internal tables.
  • Added the information_schema.crdb_contention_activity view for inspecting persisted lock and latch contention with waiting and blocking statement attribution.
  • DROP TYPE ... CASCADE is now supported, dropping the type and dependent objects including table columns of that type (while preserving the table), dependent expressions and constraints, and dependent functions, views, and domains.
  • PL/pgSQL dynamic EXECUTE now supports a USING clause to bind values to $n placeholders in the command string.
  • Added the information_schema.crdb_databases view to expose per-database metadata via stable columns (database ID, owner, survival goal, and effective zone configuration SQL), simplifying schema introspection that previously required joining multiple crdb_internal tables.
  • Added the information_schema.crdb_tables view to provide per-table metadata in a single query, including key spans, estimated row count, zone configuration SQL, and effective (inheritance-resolved) replica settings such as replica count, constraints, and lease preferences. The view returns one row per public table.
  • Added the any_value() aggregate function for PostgreSQL compatibility. It returns an arbitrary non-NULL input value (or NULL if all inputs are NULL) and can also be used as a window function.

Operational changes

  • Added twelve server.oauthbearer_authentication.* cluster settings for configuring SASL OAUTHBEARER authentication.
  • Added sixteen new SQL metrics for tracking EXPLAIN and EXPLAIN ANALYZE usage: sql.explain.started.count / sql.explain.count, sql.explain_analyze.started.count / sql.explain_analyze.count, plus four sub-counters (sql.explain.procedure.count, sql.explain_analyze.procedure.count, sql.explain.udf.count, sql.explain_analyze.udf.count and their .internal counterparts for internal queries) that fire when the EXPLAIN target is a CALL of a stored procedure or a statement that invokes a user-defined function. These statements were previously bucketed into the sql.misc.*.count series and were not visible individually.
  • Added per-store metrics that expose the CPU cost breakdown for the multi-metric allocator, including immovable, amplification, replica, sql_dist, sql_gateway, and overhead_k, to help investigate allocator-related CPU usage.
  • Reduced the default value of the kv.range_merge.queue_interval cluster setting (which controls how long the merge queue waits between processing replicas) from 5s to 200ms. This helps the merge queue keep up with range creation and reduces range accumulation.
  • Added the mma.store.shedding_overload_level metric, which reports the per-store MMA shedding severity used during rebalancing to determine whether a local store is a shedding candidate. The value is updated each rebalancing pass and ranges from 0 (low load) to 4 (urgent overload); values >= 3 indicate the store is considered overloaded for shedding purposes.
  • Added the restore.wait_for_span_config_conformance.enabled config property, which is recommended to meet data domiciling requirements if you use the STRICT option with BACKUP.
  • Execution insights are now periodically persisted to the system.statement_execution_insights and system.transaction_execution_insights tables, providing a durable, cluster-wide record that survives node restarts and outlives the in-memory window. Persistence is controlled by the new sql.insights.flush.enabled (default true), sql.insights.flush.interval (default 10m), sql.insights.flush.jitter (default 0.15), and sql.insights.flush.batch_size (default 100) cluster settings.
  • Added the admission.kv.cpu_time_token_filler.dampening.enabled cluster setting to disable runnable-goroutine-based dampening in the CPU time token filler.
  • Updated changefeed metric descriptions to indicate which metrics are not emitted by the default Kafka, Pub/Sub, and webhook (no-linger) sinks. Also clarified that Kafka batch-reduction metrics and internal retry metrics track different behaviors and are no longer co-mingled.
  • Added new metrics that count finished SQL transactions (committed or aborted) by the isolation level they ran at: sql.txn.count.serializable, sql.txn.count.snapshot, and sql.txn.count.read_committed. On the Prometheus /metrics endpoint, these are exposed as a single sql.txn.count metric labeled by isolation_level.
  • SQL CPU time is now measured for every statement and transaction instead of only for the subset selected for execution-statistics sampling. The measurement is exposed as sqlCPUTimeNanos in the crdb_internal.statement_statistics and crdb_internal.transaction_statistics tables, and SQL CPU time is now reported for all statements and transactions in executioninsights, where previously unsampled executions reported zero.
  • The raft.quota_pool.percent_used metric has been removed.
  • Bucket boundaries for histogram metrics have changed to align with Prometheus native-histogram schemas. As a result, quantiles computed from these metrics may shift. Some histograms now provide finer resolution for very low-latency operations, while others are exported at a coarser resolution to reduce the number of exported time series.
  • Added the sql.query_canceled.count metric to track statement failures due to query cancellation (for example, client context cancellation, DistSQL flow errors, or session cancellation). This helps operators distinguish cancellations from other non-retryable errors counted in sql.failure.count, alongside sql.statement_timeout.count and sql.transaction_timeout.count.
  • Added the sql.schema_changer.index_backfill_version_barrier.enabled cluster setting (default true). When enabled, an index backfill publishes an extra descriptor version and waits for it to propagate before its backfill and merge phases choose their timestamps, hardening ALTER PRIMARY KEY run concurrently with updates against a rare spurious “duplicate key value violates unique constraint” failure. This adds a short delay (up to two lease intervals per rebuilt index) to affected schema changes; set it to false to restore the previous behavior.
  • New metrics expose the behavior of the per-node table statistics cache, whose capacity is controlled by the sql.stats.table_statistics_cache.capacity cluster setting: sql.table_statistics.cache.hits and .misses count lookup outcomes; sql.table_statistics.cache.evictions.capacity and .evictions.invalidated count evictions split by cause; sql.table_statistics.cache.eviction_idle_duration records the time since last access of entries evicted for capacity (low values indicate the cache is too small for the set of tables being queried); and sql.table_statistics.cache.entries and .mem_bytes report the current cache size.
  • The following Active Session History (ASH) cluster settings are now application-level and can therefore be configured independently across separate-process virtual clusters: obs.ash.enabled, obs.ash.sample_interval, obs.ash.buffer_size, obs.ash.log_interval, obs.ash.log_top_n, obs.ash.enrichment.enabled, obs.ash.enrichment.cache.max_entries, obs.ash.enrichment.rpc.timeout, obs.ash.enrichment.queue.lifetime, obs.ash.enrichment.queue.max_entries. In shared-process deployments, ASH sampling and enrichment remain process-wide and are controlled only by the system virtual cluster (changes in secondary virtual clusters are ignored).
  • Inbound TLS handshakes are now bounded by explicit, tunable timeouts, so a peer that stalls mid-handshake can no longer hold a serving goroutine and file descriptor open indefinitely. The gRPC server bounds connection establishment (the TLS handshake plus HTTP/2 setup) at 30 seconds by default, replacing gRPC’s implicit 120-second limit; this is configurable via the COCKROACH_RPC_SERVER_CONNECTION_TIMEOUT environment variable. The DRPC server and the SQL cipher-suite allowlist path (tls-cipher-suites) bound the TLS handshake at 10 seconds by default, configurable via the COCKROACH_TLS_HANDSHAKE_TIMEOUT environment variable.
  • Breaking change: Removed the deprecated IMPORT and RESTORE event logs. Use the job status change event logs instead.
  • The obs.ash.enrichment.enabled cluster setting now defaults to true. Active Session History samples are enriched with the application name, user, plan gist, canary stats, transaction ID, and session ID of the execution that produced them, so the corresponding columns of crdb_internal.node_active_session_history and crdb_internal.cluster_active_session_history are populated without further configuration. Enrichment additionally requires the cluster version to be finalized; until then these columns remain NULL. Set the setting to false to turn enrichment off.
  • Added the cluster metric schedules.BACKUP.cluster.time_since_last_completed_by_type, which reports the time since the most recently completed full, incremental, or compaction backup (distinguished by the backup_type label) for backup schedules configured with the updates_cluster_last_backup_time_metric option. This lets each backup type’s completion cadence be monitored independently. The relevant per-type series are removed when the corresponding backup schedule is dropped.
  • Added four new basalt.tenant.* metrics to track tenant object count and byte usage (replica, logical, and archived).
  • Added metrics that provide observability into the range descriptor cache: distsender.rangecache.size, distsender.rangecache.hits, distsender.rangecache.misses, distsender.rangecache.evictions.capacity, and distsender.rangecache.evictions.stale.
  • Added the obs.ash.labels.kv_batch_key.enabled cluster setting (default off). When enabled together with obs.ash.labels.enabled, active session history samples taken while a node processes a KV batch are labeled with the batch’s start key (row values redacted when redaction is enabled) and the range ID, so samples can be attributed to the object being accessed. The crdb_internal.key_to_table_id and crdb_internal.key_to_table_index_id builtins now also accept the pretty-printed key string form stored in these labels.
  • Added the obs.ash.labels.kv_sync_wait.enabled cluster setting to emit additional Active Session History (ASH) labels for samples captured during lock and latch waits (range, table, index, and blocking statement fingerprint). These labels are emitted only when both obs.ash.labels.enabled and obs.ash.labels.kv_sync_wait.enabled are set to true. Both settings default to false.
  • Renamed metric schedules.BACKUP.cluster.time_since_last_completed to schedules.BACKUP.cluster.recovery_point_lag. The metric’s meaning is unchanged: it reports the elapsed time since the latest restorable recovery point for the backup schedule (not the backup job’s wall-clock completion time), and can be used to monitor RPO. This metric is emitted only when the updates_cluster_last_backup_time_metric schedule option is enabled.
  • Removed the schedules.backup.gc_protection.enabled cluster setting. Protected timestamp chaining for scheduled backups is now always enabled and can no longer be disabled.
  • Added cluster settings to control KV-side Active Session History (ASH) sample buffering for separate-process tenants: obs.ash.kv_sample_egress.enabled enables KV nodes to buffer KV ASH samples for tenants to pull, and obs.ash.kv_sample_egress.per_tenant_capacity / obs.ash.kv_sample_egress.total_capacity control per-tenant and total retained sample capacity.
  • The /debug/lsm endpoint, and the LSM stats included in a debug zip, now describe a store’s range-shared engines in addition to its store-local engine: the two combined, each on its own, and the individual range-shared engines with the highest read amplification, size, and compaction debt. Stores without range-shared engines are unchanged.
  • The storage metrics a store reports (rocksdb.* and storage.*) now cover its range-shared engines in addition to its store-local engine, and each is also reported broken down by engine kind under <name>.local and <name>.shared, exported as the <name>.by-engine family with an engine label. On clusters using range-shared engines, rocksdb.read-amplification and rocksdb.level-score are now the mean across a store’s engines rather than the store-local engine’s value; rocksdb.read-amplification.local and rocksdb.level-score.local report what those metrics reported before.
  • The changefeed.mvcc_ordered_buffer.bytes metric tracks the total memory and disk usage in ordered_buffer when mvcc_ordered is enabled on sinkless feeds.
  • Added basalt.fs.quorum_write.* and basalt.fs.replica_write.* metrics for clusters using disaggregated storage to report write quorum outcomes, replica-level write failures, and write latency.

Command-line changes

  • The cockroach sql CLI now supports interactive OAuth login using the OAuth 2.0 device authorization grant. Configure --oauth-issuer and --oauth-client-id (optionally --oauth-scope) to open a browser for authentication and connect using the resulting token. For security, the SQL connection must use sslmode=verify-full and the issuer must use https; for local testing with a non-HTTPS issuer, set COCKROACH_OAUTH_ALLOW_INSECURE_ISSUER to relax only the issuer requirement.
  • The cockroach debug encryption-status, cockroach debug encryption-registry-list, and cockroach debug encryption-decrypt commands can now inspect the store-local engine of a basalt store. Provide the store URI as the directory argument and pass the same basalt flags used to start the node (including --cluster-key-dir for the cluster key). The store must be offline.
  • The cockroach debug pebble subcommands now take the target database directory and files using the --dir and --file flags instead of positional arguments.

DB Console changes

  • Added a Show internal checkbox to the DB Console SQL Activity pages (Statements, Transactions, and Sessions) to include internal sessions and statement/transaction statistics without changing the sql.stats.response.show_internal.enabled cluster setting.
  • The debug zip workflow in the DB Console has been renamed as Generate Debug zip and moved under Advanced Debug > Reports. The page now acts as a command builder for cockroach debug zip, with preset configurations, category and scope selection (including time range and node selection), connection settings for local or remote clusters, and Copy/Download actions for the generated command.
  • The SQL CPU Time shown for statements and transactions in the SQL Activity and Statement/Transaction Details pages is now recorded for every execution rather than only for sampled executions. Previously most statements and transactions displayed “no samples” for SQL CPU; they now show an accurate value.
  • The DB Console Index Details page and the Indexes tab on the Table Details page now show Total Writes and Last Write for each index.

Bug fixes

  • Fixed an issue where the merge queue could repeatedly re-process ranges that could not be merged (for example, when the right-hand neighbor had an unexpired sticky bit), potentially starving other mergeable ranges. The merge queue now backs off before retrying an unmergeable range; this cooldown is configurable via the kv.range_merge.cooldown cluster setting.
  • Fixed an issue where a partitioned index scan on a JSONB column could generate an empty key span and fail with end key must be greater than start.
  • Fixed a bug that could cause an initial-scan changefeed with diff enabled, or a CDC query using cdc_prev, to fail with a GC threshold error if garbage collection ran during the scan.
  • Fixed a bug where CREATE TEMPORARY TABLE could fail with an internal error in the same session after the session’s first temporary table creation was rolled back.
  • Fixed a bug where Avro-enriched changefeed messages could emit stale values for source.ts_ns, source.ts_hlc, and source.mvcc_timestamp, repeating the timestamp from an earlier event instead of the current event.
  • Fixed a bug where importing Avro data with large records could cause unbounded memory growth, slowing or stalling the import. Such records now fail with a clear error suggesting that the max_row_size option be increased.
  • Fixed a bug where DISTINCT ON queries with ORDER BY could return incorrect results during distributed execution when the operation spilled to disk (for example, due to memory pressure).
  • Fixed an issue where cockroach debug job-trace could fail with “column “trace_id” does not exist”. If no trace is available for the requested job, the command now reports that clearly.
  • Fixed a bug where CREATE SCHEMA with an empty quoted schema name (for example, "") could trigger an internal error. It now returns a user-facing syntax error.
  • Fixed a bug where MATCH FULL foreign key validation during schema changes could fail with a syntax error if the table’s primary key included column names that require quoting (for example, names containing hyphens).
  • Fixed a bug where range-based lookup joins could rarely return incorrect results when the lookup column had redundant inequality filters (for example, k >= 1 AND k >= 0).
  • Fixed an issue where calling a procedure, or invoking a user-defined function (UDF) in a query, in the same implicit-transaction statement batch that created or replaced it could fail with a “function does not exist” error if the transaction was automatically retried.
  • Fixed a bug where binding a prepared EXPLAIN or EXPLAIN ANALYZE statement could fail with the error “EXPLAIN ANALYZE can only be used as a top-level statement”.
  • Fixed an issue where the MVCC GC queue per-range score was fully redacted in logs, which could obscure GC diagnostics in redacted debug output.
  • Fixed a bug where execution statistics (for example, contention time, CPU time, and MVCC iterator statistics) from earlier attempts of an automatically retried transaction were discarded. crdb_internal.transaction_statistics, the DB Console SQL Activity page, and the sql.txn.contended.count metric now reflect execution across all retry attempts, consistent with the transaction’s service latency and retry count. Data-volume statistics (rows read/written, bytes read, and rows affected) continue to reflect only the final attempt.
  • Fixed an issue where a transient error during the non-revertible stage of a declarative schema change could cause the schema change job to enter an infinite rollback/replan loop.
  • Fixed an issue that could cause a lost write when a transaction used buffered writes, set lock_timeout, and attempted to continue after a lock-timeout error by issuing ROLLBACK TO SAVEPOINT.
  • Improved the multi-metric allocator (MMA) (preview) to exclude down, dead, or decommissioned stores when computing cluster-wide load averages for overload detection. This prevents stale load from unavailable stores from skewing rebalancing decisions.
  • Fixed an issue where workload_index_recs could return duplicate index recommendations and omit others when multiple recommendations for the same table shared a common column prefix.
  • Fixed an issue where a schema change could hang indefinitely when system.lease contained leases held by many expired SQL sessions, which could also block other schema changes across the cluster.
  • Fixed an issue where SHOW CREATE FUNCTION (and other schema output) could emit non-parseable SQL for a routine with a parameter named index, especially when the parameter type normalizes to a parenthesized form (for example, BIT VARYING(61) ARRAY).
  • Fixed an issue in Logical Data Replication (LDR) where last-write-wins (LWW) conflict resolution could incorrectly drop a newer incoming row. This could happen when replicating tables with rows larger than ~3 KiB, where paginated reads might omit the MVCC origin timestamp required for conflict resolution.
  • Fixed an issue where node decommission pre-checks could fail spuriously if candidate target stores were temporarily snapshot-throttled after a snapshot reservation was rejected.
  • Fixed an issue where a transaction using buffered writes could return incorrect (including misordered) results for some queries that combine range scans and point lookups, particularly when a scan limit was reached and some point lookups were served from buffered data. Also fixed an issue where request statistics (keys/bytes read) could be underreported for point lookups served from buffered data.
  • Fix a bug that would allow a CHANGEFEED to emit an incorrect prev_value when the disable_changefeed_replication option was used during a DELETE.
  • Fixed a memory accounting leak in the rangefeed buffered sender. When a client’s gRPC stream failed, budget allocations for events that had been dequeued but not yet sent were never returned to the per-range rangefeed memory budget. Repeated stream failures could cause rangefeed consumers of the affected range to be disconnected with spurious “budget exceeded” errors.
  • Fixed an issue where pg_advisory_xact_lock or pg_advisory_xact_lock_shared could be silently lost while a transaction was still open (for example, during a range split or lease transfer) when write buffering was enabled. This could allow another session to acquire the same advisory lock concurrently.
  • Fixed a bug that caused some queries to fail with the error “could not decorrelate subquery with mutation”. This could happen when a correlated subquery’s input performed a mutation, such as a PL/pgSQL routine (including a trigger function) with a loop containing a SELECT ... INTO statement that also performed an INSERT, UPDATE, or DELETE.
  • Fixed a bug where a user could intermittently be denied a role membership immediately after it was granted.
  • Fixed a bug where disabling or re-enabling an external statement hint via information_schema.crdb_enable_statement_hints did not invalidate cached query plans that depended on the hint.
  • Fixed a bug where query text shown in SHOW CLUSTER QUERIES, SHOW CLUSTER SESSIONS, and the corresponding crdb_internal virtual tables could be truncated more aggressively than the configured limit when the text contained U+FFFD replacement characters near the truncation point.
  • Fixed a bug where a Logical Data Replication (LDR) stream created by a non-admin user could fail to write to its dead letter queue (DLQ) due to insufficient privileges.
  • Fixed a bug where large Raft commands (for example, AddSSTable operations used by index backfills, IMPORT and RESTORE) could be starved indefinitely on ranges with concurrent foreground writes. This could trip the per-replica circuit breaker and surface “replica unavailable … slow proposal” errors even though the range was otherwise healthy.
  • Fixed a bug where Active Session History (ASH) samples for SQL statements waiting on admission control (work events sql-kv-response and kv-elastic-cpu-queue) could be missing the application name and were not enriched with attributes such as user, transaction, session, or plan gist.
  • Fixed a bug where a failure to delete an expired descriptor lease left a stale row in system.lease for as long as the owning node stayed up. The stale row could cause schema changes (such as DROP TABLE or DROP DATABASE) on that descriptor to hang indefinitely until the node holding the stale lease was restarted.
  • Fixed a bug where an ALTER PRIMARY KEY on a REGIONAL BY ROW table with an inverted index could fail validation with an internal error.
  • Fixed a bug that caused an internal error when creating a SQL or PL/pgSQL routine with polymorphic parameters (such as ANYELEMENT) whose body passed a polymorphic parameter as an argument to another routine expecting a concrete type. This now returns a clear error indicating the case is not yet supported.
  • Changefeeds created with the execution_locality option no longer fail permanently if no nodes matching the filter are momentarily available, such as during a brief connectivity outage. The changefeed now retries instead.
  • EXPLAIN ANALYZE now reports accurate per-operator execution statistics for statements inside UDF and stored procedure bodies; they were previously nondeterministic. The reported statistics reflect a single invocation of the routine.
  • EXPLAIN ANALYZE could attribute execution statistics from unrelated parts of the query to operators of plans created during execution (routine bodies, FK cascades, triggers).
  • Fixed a bug where a crash during the initial bootstrap of a new cluster could leave the first store looking initialized while missing its data, causing the node to hang on startup and cockroach init to be refused. Such a store is now correctly treated as uninitialized; the partially written store must be cleared before cockroach init can be retried.
  • CREATE TENANT now fails with a clear error if the RANGE tenants zone configuration is invalid, instead of creating a tenant that cannot finish starting up.
  • ALTER RANGE default ... CONFIGURE ZONE now rejects a change that would make an inheriting named range (such as RANGE tenants) invalid, instead of silently producing an invalid inherited configuration.
  • An INSERT or UPDATE that writes the referencing columns of a foreign key no longer requires the writing user to hold the SELECT privilege on the referenced table, matching PostgreSQL. The foreign-key existence check is authorized by the constraint itself, whose creation already required the REFERENCES privilege on the referenced table.
  • Fixed a bug where ALTER RANGE ... RELOCATE and ALTER RANGE ... RELOCATE LEASE loaded every range descriptor in the cluster into memory on each statement, even when relocating a single range. On clusters with a very large number of ranges, running many concurrent RELOCATE statements through a single node could exhaust memory and crash that node. These statements now read only the descriptors for the ranges being relocated.
  • Zero-argument PL/pgSQL routines now display empty parentheses after the function name in error CONTEXT reporting, matching PostgreSQL.
  • Fixed an internal error (“inconsistent Case return types”) that could occur when a CASE expression referenced a column produced by unnesting a constant array whose only element was a typed NULL, such as unnest(ARRAY[NULL]::TEXT[]).
  • Fixed a bug where the chunk_size option to EXPORT INTO PARQUET was ignored, so files were rotated only by chunk_rows. EXPORT now bounds the approximate size of each parquet file as documented.
  • Fixed an internal error “inconsistent Case return types” that could occur when an IFERROR expression with a NULL first argument was used as a branch of a CASE expression.
  • Fixed an internal error (“inconsistent Case return types”) that could occur for CASE, IF, or NULLIF expressions when one branch was constant-folded to NULL. In addition, CASE and IF expressions over RECORD-returning user-defined functions with different result types now return a clear user-facing error instead of an internal error.
  • Fixed a bug where a node configured with a TLS cipher-suite allowlist (via the tls-cipher-suites flag) could stop accepting new TLS connections when a single client handshake stalled. Cipher-suite enforcement held a process-global lock across the TLS handshake, so one stalled handshake serialized all new SQL, HTTP, and RPC connection attempts on the node. This bug was present in v24.1.18, v24.3.14, v25.1.7, v25.2.0, v25.3.0, and all later releases on those branches.
  • Fixed a bug where planning a query with a filter that negates a wide disjunction (e.g. WHERE NOT (b1 OR ... OR bN)) could consume very large amounts of memory and potentially crash the node, before any rows were read. The optimizer now bounds this work via the new optimizer_max_disjunction_split_count session variable.
  • Errors with uncategorized SQLSTATE codes and retryable errors in PL/pgSQL blocks with non-matching exception handlers now include the PostgreSQL-compatible CONTEXT field identifying the routine and line number. The line number is computed from CockroachDB’s reformatted function body and may differ from PostgreSQL’s when the original source contains blank lines or unusual indentation.
  • The cloud.read_bytes and cloud.write_bytes metrics now account for bytes transferred via external storage opened during early boot (such as the remote storage used by online restore); previously these bytes were omitted.
  • Fixed a rare race condition that could crash a node with a “pebble: batch already committing” error when a query buffered results that spilled to disk and then read them back concurrently (e.g. a query referencing a materialized common table expression multiple times).
  • Fixed a bug where a statement using a lock timeout (via the lock_timeout session variable) could occasionally fail with a bare “context deadline exceeded” error instead of the expected lock-timeout error while waiting on a conflicting lock. This was more likely under heavy load.
  • CREATE TABLE ... AS <query> with data inside a stored procedure is now rejected with a clear ‘not supported’ error at procedure-creation time, instead of failing at call time with a confusing ‘table is being added’ error. CREATE TABLE ... AS ... WITH NO DATA and plain CREATE TABLE remain supported inside stored procedures.
  • Fixed a panic that could occur when using = ANY(ARRAY[...]) with an array whose element type differs from the compared column’s type.
  • Fixed a bug where a query using OFFSET could incorrectly return an empty result instead of an error when the transaction_rows_read_err session setting was enabled and the offset exceeded the configured row-read limit.
  • Fixed a bug where DDL run inside a PL/pgSQL block whose exception handler caught an error remained visible to the rest of the transaction, so a later statement in the same routine could resolve an object that had been rolled back, or re-creating an object with the same name could fail with a spurious “already exists” error.
  • Fixed a bug where SHOW BACKUPS would not include a leading slash when listing from prefixless collection URIs.
  • Fix a bug that could result in a transaction being unexpectedly committed by transaction recovery, resulting in a transaction status error with REASON_TXN_COMMITTED when the transaction attempts to commit.
  • Fix a bug where a range split could drop the rolled-back sequence number information associated with an unreplicated lock, potentially allowing a lock needed by a transaction to be released early after a savepoint rollback.
  • Fixed a bug where a table column default that called a multi-argument sequence builtin such as setval() was stored incorrectly, causing later introspection and DROP TABLE to fail with an internal error.
  • Fixed a bug where using FETCH ABSOLUTE on a holdable cursor after the transaction was committed could return unexpected errors.
  • Fixed a bug where a changefeed could crash with an internal error like got a span level timestamp ... that is less than the initial high-water after being replanned (for example, after changing its sink destination via an external connection).
  • Fixed a bug where a failed ALTER DOMAIN ... SET DEFAULT or ALTER DOMAIN ... DROP DEFAULT could roll back incorrectly and leave the domain default in an inconsistent state for subsequent statements. This schema change is a metadata-only change that cannot be rolled back.
  • Fixed a bug where a changefeed could fail permanently with an error like “cannot create external storage before init” if an aggregator was scheduled onto a node (or virtual cluster) that was still starting up. This transient condition is now retried until the node finishes initializing.
  • Fixed a bug where the optimizer could return incorrect results when a column was compared to a constant of an equivalent but different type (for example, a NAME column compared to a string literal) and a type-sensitive expression such as pg_typeof was applied to the same column. In some cases, the optimizer could substitute the constant using the wrong type, changing the result of the type-sensitive expression.
  • Fixed a bug where a prepared statement sent over the PostgreSQL extended wire protocol and referencing a user-defined type (such as an enum) could fail with an internal error (“comparison of two different versions of enum”) if the type definition changed between statement preparation and execution.
  • Fixed a bug where ALTER TABLE ... ADD CONSTRAINT ... PRIMARY KEY could panic if the primary key definition included an expression (for example, PRIMARY KEY ((expr))). Such expressions are now rejected with a clear error message.
  • Fixed an internal error when creating a function that returns the record type of a virtual table; it now returns a proper error.
  • Fixed a bug where a transaction that performed a schema change could hang forever at commit time in the two-version invariant check after an internal automatic transaction retry.
  • Fixed a bug where filtering an inverted-indexed array column with the @> containment operator could return an internal error if the right-hand array contained a NULL element.
  • Fixed a rare issue that could cause an internal error like “unexpected replacement: original vector is …” during SQL query execution.
  • Fixed a bug where the SECURITY DEFINER option on a trigger function was silently ignored: the trigger body ran with the invoking user’s identity and privileges instead of the function owner’s. Trigger functions declared SECURITY DEFINER now execute as the function owner, matching PostgreSQL, so current_user and privilege checks inside the trigger body resolve to the owner.
  • Fixed an internal error when a CREATE DOMAIN statement’s CHECK constraint contained a subquery. Domain CHECK constraints containing subqueries or aggregate, window, set-returning, or procedure calls are now rejected by CREATE DOMAIN and ALTER DOMAIN instead of being accepted and failing later.
  • Fixed a bug where preparing EXECUTE p and then re-preparing p with a different set of result columns caused an internal error. CockroachDB now returns the expected cached plan must not change result type error.
  • Fixed a bug in the declarative schema changer where DROP INDEX could fail with a spurious cannot drop index ... because <function/view> depends on it error when an unrelated table had an index with the same numeric index ID that was referenced by a dependent function or view.
  • Error messages that block a schema change because a procedure depends on the affected object now refer to the dependent object as a “procedure” rather than a “function”.
  • Fixed a bug in the declarative schema changer where creating an index whose temporary-index merge was interrupted more than once (e.g. by node restarts, retriable errors, or pause/resume) re-merged already-completed work on each retry, making the schema change slow to finish.
  • Fixed a bug where RESTORE with the skip_missing_sequences option could fail with an internal validation error when a column’s DEFAULT expression referenced multiple sequences and only some of those sequences were included in the restore.
  • Fixed a performance bug where the job that refreshes the table metadata cache used by the DB Console Databases and Tables pages could take time quadratic in the number of tables when checking for stale cache entries. This could significantly delay updates to reported table sizes, replica counts, and statistics timestamps on clusters with many tables.
  • Fixed a rare bug that could lead to a linearizability violation.
  • Fixed a bug where creating a PL/pgSQL function or running a DO block could fail with a parse error if a RAISE statement’s message contained doubled single quotes (for example, RAISE EXCEPTION 'it''s invalid').
  • Fixed a bug where crdb_internal.kv_repairable_catalog_corruptions reported a session’s temporary schema as corruption and crdb_internal.repair_catalog_corruption deleted it, which stopped automatic temporary object cleanup from finding the session’s tables and left their data on disk.
  • Fixed a rare bug where a follower read issued while the replica serving it was applying a split or a snapshot that narrowed its key bounds could omit rows that were committed and still present in the range, rather than being re-routed to the replica that owns them.
  • Fixed a bug where calling pg_get_function_arguments or pg_get_function_identity_arguments on certain built-in array functions could return an internal error (“unknown PG name for oid”) and potentially crash catalog introspection queries that scan all functions.
  • Fixed a bug where querying crdb_internal.cluster_queries, crdb_internal.node_queries, or SHOW QUERIES could fail with an “index out of range” error if an active query contained placeholder tokens (for example, $1) but no captured placeholder values. These views now return results and display the original placeholder token when the value is unavailable.
  • Fixed a rare bug where a statement could be applied twice when it was internally retried after the transaction deadline was exceeded (for example, due to an expired descriptor lease or SQL liveness session). This could result in spurious duplicate-key errors or duplicated rows for INSERT statements with generated primary keys.
  • Fixed a bug where some queries involving the trigger pseudo-type (for example, via the trigger_in builtin) could return an internal error or crash. These queries now fail gracefully with a user-facing error instead.
  • Fixed a bug where a prepared statement that referenced a table via a non-default search_path could stop working after its connection was migrated between nodes, failing on execution with a result-shape error even though it worked before the migration.
  • Statement bundles collected via EXPLAIN ANALYZE (DEBUG) and statement diagnostics no longer include the values of sensitive cluster settings (such as authentication secrets) in env.sql, even when collected by a privileged user. A comment indicates when a sensitive setting differs from its default.
  • Sort arrows on the Indexes tab of the Table Details page in DB Console had no effect. The Last Read, Total Reads, Last Write and Total Writes columns now sort.
  • Fixed a bug where pg_locks and crdb_internal.cluster_held_advisory_locks could report a transaction-scoped advisory lock as held after a statement in a READ COMMITTED transaction acquired the lock and was then automatically retried. The underlying lock state in KV was always correct; only these observability views were affected.
  • Fixed a bug where a prepared statement comparing a TIMESTAMPTZ column with a TIMESTAMP or DATE constant could return incorrect results when executed under a session time zone different from the one used at prepare time.
  • Fixed a bug where comparing an INT column to a FLOAT constant with magnitude 2^53 or larger could incorrectly return no rows.
  • Fixed a bug where adding an incremental backup to a scheduled backup did not re-enable protected timestamp chaining, which could allow required data to be garbage-collected before the incremental backup could read it.
  • Fixed a bug where a cluster RESTORE that was paused, or whose coordinator node failed, after its system tables had been restored but before the job completed would fail on resumption with an error such as restoring system table users: has-column: relation "crdb_temp_system_<id>.users" does not exist. Such a restore now resumes successfully.
  • Fixed a bug where a job that failed into a terminal state could delay returning its error to a synchronous caller by up to the job adoption interval. For example, some invalid CREATE STATISTICS statements could appear to hang before surfacing their error.
  • Fixed a bug where BACKUP and RESTORE of an individual table with a column of a user-defined DOMAIN type did not include the domain’s base type, which could leave the restored table unusable.
  • Fixed a rare bug where a follower read that pinned engine state while the serving replica was applying a split or a snapshot that narrowed its key bounds, and that only completed its validity checks after a subsequent merge restored those bounds, could silently omit committed rows.
  • PL/pgSQL routines with a polymorphic (ANYELEMENT, ANYARRAY) parameter or return type no longer fail at definition time with unable to coerce type <t> to anyelement when the body assigns or returns an expression of some other type. The coercion is now checked against the concrete argument type at each invocation, as PostgreSQL does.
  • Fixed an assertion failure that could occur when a DOMAIN type used a CHECK constraint containing a range condition.
  • Fixed a bug where TSVECTOR or TSQUERY values containing lexemes with a backslash (\) or a single quote (') could be corrupted or fail to parse when round-tripping through their text representation (for example, during EXPORT followed by IMPORT).
  • Fixed a bug where crdb_internal.sstable_metrics could ignore its end_key argument and report SSTables for only a single key instead of the requested key span.
  • Fixed a bug that could crash a node when a DECLARE CURSOR statement in an explicit READ COMMITTED transaction was automatically retried (for example, after a transaction conflict).
  • Fixed a bug that could cause queries with inequality predicates (for example, != 'null') on a JSONB column in a forward (non-inverted) index to silently miss rows where the JSONB value was an empty array ([]).
  • Fixed a bug where SHOW PARTITIONS and other queries that look up rows in crdb_internal.table_indexes by descriptor ID could fail with an “unknown schema” error when a dropped table was still awaiting garbage collection after its parent schema had been deleted.
  • Improved schema change error messages by removing internal plan stage details from user-facing errors.
  • Fixed a bug where cockroach debug encryption-active-key reported Plaintext for encrypted stores. The command now reports the active store key’s encryption algorithm and key ID.
  • Fixed a bug where creating a vector index with an ENUM prefix column could fail with an assertion error.
  • Fixed a bug where planning a JOIN with an ON clause containing many OR-connected equality conditions could use excessive memory and potentially crash a node before reading any rows. Planning work for these cases is now bounded by the optimizer_max_disjunction_split_count session setting.
  • Fixed a compatibility issue where BACKUP, RESTORE, and SHOW BACKUPS could fail against some S3-compatible object stores that require single-character delimiters when listing objects (for example, Alibaba OSS).
  • Fixed a bug where CREATE TRIGGER specifying a built-in function as the trigger function (for example, EXECUTE FUNCTION now()) could return an internal error instead of reporting that the function must return type trigger.
  • Fixed a bug where ALTER TABLE ... SET LOCALITY REGIONAL BY ROW AS ... could fail with an internal error when the table was already REGIONAL BY ROW and its primary key was hash-sharded.
  • Fixed a bug where hitting statement_timeout inside an explicit transaction could leave the transaction in an unrecoverable aborted state. Explicit transactions can now be recovered with ROLLBACK TO SAVEPOINT, matching PostgreSQL behavior.
  • Fixed a bug where setting up a Physical Cluster Replication (PCR) readable standby (read-only virtual cluster) could fail to initialize its catalog if the replicated cluster contained a materialized view, preventing the standby from starting.
  • Fixed a bug where changefeeds created WITH diff could emit confusing delete messages with both before and after images set to NULL. This could occur on REGIONAL BY ROW tables under READ COMMITTED or SNAPSHOT isolation, or when deleting a non-existent row from a table with no secondary indexes.
  • Fixed a bug where a failed backup compaction job could leave a stale BACKUP-LOCK file in external storage, blocking subsequent compaction attempts to the same destination until the lock was removed.
  • Fixed a bug where the optimizer could nondeterministically choose between a constrained index scan and a full scan for queries with an equality filter on an expression that is the key of multiple partial expression indexes.
  • Fixed a bug where width_bucket(operand, thresholds[]) could silently accept NULL elements in the thresholds array and return an incorrect bucket index. It now returns an error (thresholds array must not contain NULLs) if thresholds contains any NULL, matching PostgreSQL behavior.
  • Fixed a bug where make_date(), make_timestamp(), and make_timestamptz() could silently normalize out-of-range month, day, hour, minute, or second values into a different valid date or time. These functions now return a “date/time field value out of range” error for invalid inputs (matching PostgreSQL), and validate day values against the actual month length (including leap years).
  • Fixed a bug where starting a node with --accept-proxy-protocol-headers caused it to reject connections that did not begin with a PROXY protocol header. Nodes now accept direct connections (for example, health probes and cockroach init) and honor the PROXY header only when it is present.

Performance improvements

  • SHOW CHANGEFEED JOBS is now significantly faster and uses less temporary storage when listing changefeeds that watch many tables.
  • Improved performance for some correlated EXISTS and IN subqueries that include UNION ALL. These queries can now be planned as more efficient (non-apply) joins instead of re-evaluating the subquery once per outer row, which can substantially speed up execution when the outer input is large.
  • Improved performance of queries against crdb_internal.kv_repairable_catalog_corruptions, which are now significantly faster on clusters with many descriptors.
  • Reduced the memory footprint of the table statistics cache: cached merged and forecast statistics no longer retain an extra encoded copy of their histograms in addition to the decoded form used by the optimizer.
  • Sped up scans of crdb_internal.create_statements on clusters with many tables, which previously scaled quadratically with the number of tables and could cause debug zip collection to time out on large-schema clusters.
  • Added the cloudstorage.gs.transport_shard_count cluster setting. When set above 1, CockroachDB shards reads from Google Cloud Storage across that many HTTP connections, which can substantially increase read throughput for bulk operations such as online restore. Defaults to 0 (a single connection, as before).
  • Reduced per-statement latency for queries against tables with row-level security (RLS) enabled. Previously, every such statement performed an uncached read of the system.role_options table to evaluate the BYPASSRLS exemption, adding a round-trip (potentially cross-region, since system.role_options is a single global table) to every query regardless of the number of rows scanned. This read is now cached and skipped while the relevant role state is unchanged.
  • Repeatedly resolving an unqualified name that does not exist (for example, a user-defined type referenced by an unqualified name under a non-public schema) within a single transaction no longer performs redundant reads of system.namespace for each occurrence, reducing latency for such workloads.
  • Online restore now begins downloading data as soon as the link phase completes, rather than waiting for the next job adoption cycle.
  • Added the cloudstorage.s3.chunked_upload.concurrency cluster setting to control how many parts a single object upload to Amazon S3 can upload in parallel. Increasing this setting can improve upload throughput for large files.
  • Improved performance for queries with CROSS JOIN (and outer joins with an always-true join condition) and a constant LIMIT by avoiding full scans of join inputs in more cases.

Build changes

  • Upgraded the Kafka client library used by changefeeds to improve producer resilience during Kafka broker restarts and transient network failures.

Miscellaneous

  • Added support to restore from encrypted backups with online fast (WITH EXPERIMENTAL COPY) restores. This functionality requires that the backup was taken on a 26.4 or later cluster, and that encryption at rest is enabled for all stores in the restoring cluster.
  • Added the scheduled backup metric schedules.BACKUP.cluster.time_since_last_completed, which reports the time since the last successful backup (RPO) for a schedule without requiring additional aggregation or calculation.
  • Added support for recommending inverted (GIN) indexes on ARRAY and STRING columns in the index recommendation engine, improving recommendations for queries that use array containment operators (such as @> and <@) and LIKE/ILIKE predicates.
  • This patch introduces a format change for encrypted backups. Encrypted backups will use this format by default starting in 26.4. Restores work with both formats.
  • Running a RESTORE ... WITH EXPERIMENTAL COPY now outputs the same 4 column result as traditional restore. RESTORE ... WITH EXPERIMENTAL DEFERRED COPY keeps the same 5 column result.
  • Fixed an issue which can lead to too many WAL files written in the WAL failover location, causing out-of-disk.

v26.4.0-alpha.2

Release Date: September 16, 2026

Downloads

CockroachDB v26.4.0-alpha.2 is a testing release. Testing releases are intended for testing and experimentation only, and are not qualified for production environments and not eligible for support or uptime SLA commitments.
Experimental downloads are not qualified for production use and not eligible for support or uptime SLA commitments, whether they are for testing releases or production releases.
Operating SystemArchitectureFull executableSQL-only executable
LinuxIntelcockroach-v26.4.0-alpha.2.linux-amd64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.2.linux-amd64.tgz
(SHA256)
ARMcockroach-v26.4.0-alpha.2.linux-arm64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.2.linux-arm64.tgz
(SHA256)
Mac
(Experimental)
Intelcockroach-v26.4.0-alpha.2.darwin-10.9-amd64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.2.darwin-10.9-amd64.tgz
(SHA256)
ARMcockroach-v26.4.0-alpha.2.darwin-11.0-arm64.tgz
(SHA256)
cockroach-sql-v26.4.0-alpha.2.darwin-11.0-arm64.tgz
(SHA256)
Windows
(Experimental)
Intelcockroach-v26.4.0-alpha.2.windows-6.2-amd64.zip
(SHA256)
cockroach-sql-v26.4.0-alpha.2.windows-6.2-amd64.zip
(SHA256)

Docker image

Multi-platform images include support for both Intel and ARM. Multi-platform images do not take up additional space on your Docker host. Within the multi-platform image, both Intel and ARM images are available for testing. To download the Docker image:

Backward-incompatible changes

  • Removed the experimental, unsupported COCKROACH_S3_LIST_WITH_PREFIX_SLASH_MARKER flag.

Security updates

  • Redacted secret values for changefeed schedule options (for example, webhook_auth_header) in the command column of SHOW SCHEDULES, in addition to sanitizing the sink URI.
  • The values of the changefeed options webhook_auth_header, extra_headers, and confluent_schema_registry, which can contain credentials, are now redacted by default when a changefeed statement is reformatted for display (e.g. in SHOW CREATE SCHEDULE), matching the existing handling of changefeed sink URIs.

General changes

  • Changed the default value of the sql.insights.anomaly_detection.memory_limit cluster setting to 10MiB (from 1MiB), so SQL Insights can keep more statement fingerprints in memory for anomaly detection. SQL Insights now records execution latencies for all statements to improve anomaly detection coverage, including for statements that are usually below the latency threshold. The latency threshold still controls which statements are surfaced as insights.
  • With jobs.execution.panic_recovery.enabled set, a crash in a processor running part of a job can now fail the job instead of bringing down the nodes running that job’s work.
  • Added the cluster setting jobs.execution.panic_recovery.enabled to prevent a job panic from crashing the node running the job. When enabled, the job is failed (or paused if it panics while reverting), and the panic backtrace is recorded on the job. Nodes that recover a panic increment jobs.execution.panics_recovered and should be restarted.

SQL language changes

  • Fixed a bug where LOOKUP JOIN or MERGE JOIN hints could fail with an error like “could not produce a query plan conforming to the … hint” when the join condition compared columns using a value-preserving cast. These predicates are now recognized as equijoins, allowing the hinted plan to be produced and avoiding fallback to an inefficient cross join.
  • The optimizer_span_limit session setting now also bounds the number of spans the optimizer can generate for queries that use inverted, vector, and trigram indexes, helping avoid excessively large span sets.
  • Added consistency checks for supported partial indexes in INSPECT TABLE and INSPECT DATABASE; selecting a partial index with the INDEX option no longer returns an error.
  • SHOW CREATE TABLE now lists a column family’s members in column-ID order for tables created after this change, rather than in the order the FAMILY clause named them. Families of existing tables are unaffected, and generated family names are unchanged.
  • Added the information_schema.crdb_stores view to list per-store metrics (including node_id, range and lease counts, under/over/unavailable-replicated range counts, capacity/available/used bytes, percent available, and attributes) using stable, named columns instead of requiring JSON parsing of crdb_internal.kv_store_status. This view is not supported in secondary tenants.
  • CREATE TEMPORARY TABLE now supports the Postgres ON COMMIT DELETE ROWS and ON COMMIT DROP options, in addition to the existing ON COMMIT PRESERVE ROWS default. ON COMMIT DELETE ROWS removes all rows at the end of every successful transaction. ON COMMIT DROP drops the table when its creating transaction commits. Temporary tables remain gated by the experimental_enable_temp_tables session setting. When autocommit_before_ddl is enabled, CREATE TEMPORARY TABLE ... ON COMMIT DROP itself is exempt, but other DDL can still commit the transaction and drop the temporary table before that statement runs.
  • Changed IMPORT INTO for REGIONAL BY TABLE tables to default execution_locality to the table’s home region when the option is not specified, which can reduce cross-region traffic. Set execution_locality = '' to opt out and run unconstrained.
  • Implemented the ST_ForceRHR(geometry) builtin function, a synonym of ST_ForcePolygonCW that returns a geometry whose polygon exterior rings are clockwise and interior rings counter-clockwise (non-polygon objects are unchanged), matching PostGIS behavior.

Operational changes

  • Added cluster settings to control collection of KV-layer Active Session History (ASH) samples for separate-process tenants: obs.ash.kv_sample_pull.enabled enables or disables pulling KV-side ASH samples into the tenant. obs.ash.kv_sample_pull.interval sets how frequently the tenant pulls KV-side ASH samples.
  • Added the sql.routine.dynamic_execute.started.count and sql.routine.dynamic_execute.count metrics, which count statements run through a PL/pgSQL dynamic EXECUTE.
  • Changed routine statement metrics so SQL statements executed via PL/pgSQL EXECUTE are now counted in the corresponding sql.routine.<type>.count metrics (for SELECT, INSERT, UPDATE, and DELETE), and are also tracked separately in the new sql.routine.dynamic_execute.* metrics.
  • Updated the --external-io-dir help text to clarify that passing an explicitly empty value (--external-io-dir=) disables local file I/O, and that disabled is treated as a directory name (not a special value).

DB Console changes

  • Updated the DB Console UI to match the latest Cockroach Labs branding: Updated the color palette and adjusted UI surfaces (white content area with a warm-gray sidebar). Updated typography to use Geist and Geist Mono. Updated the logo and favicon.
  • Changed the DB Console on Basalt-backed clusters to show only Storage Used (bytes stored) and hide usable, available, and maximum capacity values and percent used.

Bug fixes

  • Fixed a bug where a KV request sent to a learner replica (for example, due to a stale cached range descriptor) could return a “replica unavailable” error instead of redirecting to the leaseholder, causing unnecessary latency.
  • Fixed a bug where TRUNCATE could incorrectly treat indexes backing UNIQUE constraints as explicitly created, allowing DROP INDEX to drop them without requiring CASCADE.
  • Fixed an issue where OpenID Connect (OIDC) single sign-on logins to the DB Console could block one another when the identity provider was slow or unavailable.
  • Fixed a bug where ALTER TYPE ... DROP VALUE could succeed even when the enum value was referenced as an explicitly typed constant in a trigger WHEN condition or trigger function body. This could leave the trigger in an invalid state and cause subsequent INSERT, UPDATE, and DELETE statements on the table to fail; ALTER TYPE ... DROP VALUE now returns an error in this case. References where the constant’s type is only implied by the column it is compared against (for example, WHEN (NEW.c = 'a')) are not yet detected.
  • Fixed a rare race condition in IMPORT progress tracking that could compute an incorrect resume position, causing some rows to be skipped when an IMPORT job was resumed.
  • Fixed a bug where sessions with default_int_size=4 could have unqualified INTEGER types re-resolved as INT8 during automatic transaction retries or when prepared statements were refreshed after a referenced user-defined type changed, which could cause client decode errors for 32-bit integers.
  • Fixed a bug that could cause queries using a partial index to scan more rows than necessary when the index predicate referenced leading index key columns.
  • Fixed a bug where RESTORE TABLE db.schema.* could fail with an internal error if the restore target contained a user-defined function that referenced objects in another, non-restored schema; restore now either succeeds by including required function/type dependencies or fails with a clear error when it depends on missing table/view/sequence objects.
  • Fixed a bug where planning a query with an inverted-index filter over a very large value (for example a JSON array containment with thousands of elements, or a long trigram or tsquery match) could cause the node to run out of memory during query planning. Such filters now respect the optimizer_span_limit session setting and fall back to a non-accelerated scan when the limit is exceeded.
  • Fixed a rare row-based DistSQL bug that could cause queries to fail with the internal error decoding unset EncDatum after an INTERVAL overflow during stream encoding.
  • Fixed a rare data race that could cause a node to crash when automatic statistics setting overrides for a table were updated concurrently with query planning. This issue could occur only when the sql.log.scan_row_count_misestimate.enabled cluster setting was enabled (it is disabled by default).
  • Fixed a bug that could acknowledge a Raft log write before it was durable when the write required a sync but carried no data, risking the loss of an acknowledged entry on a crash. Only test builds were affected; production deployments are not.
  • Fixed a bug where an error raised inside a PL/pgSQL EXCEPTION handler could be matched to the wrong enclosing EXCEPTION clause, causing the wrong handler to run or the correct enclosing handler to be skipped.
  • Fixed a bug where a REGIONAL BY TABLE IN <region> table in a multi-region database with a secondary region could be assigned incorrect lease preferences. This bug was only in the declarative schema changer and affected tables set to REGIONAL BY TABLE IN <region> via ALTER TABLE ... LOCALITY in 26.2+.
  • pg_catalog.pg_depend reported the wrong column for a view depending on a column whose type had been changed by an ALTER COLUMN TYPE that rewrote on-disk data.
  • Foreign key, check, unique, and NOT NULL constraints on a column whose type had been changed by an ALTER COLUMN TYPE that rewrote on-disk data were not visible to tools that inspect constraints through pg_catalog.pg_constraint, such as ORMs. The constraints were still enforced.
  • Fixed a bug where the optimizer could not use indexes on OID-typed columns (such as in pg_catalog) when the column was compared to an integer constant or parameter (for example, a client driver binding the value as int4 or int8), which could cause a full table scan.