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.
- 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 .
v26.4.0-alpha.1
Release Date: September 9, 2026Downloads
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 System | Architecture | Full executable | SQL-only executable |
|---|---|---|---|
| Linux | Intel | cockroach-v26.4.0-alpha.1.linux-amd64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.1.linux-amd64.tgz (SHA256) |
| ARM | cockroach-v26.4.0-alpha.1.linux-arm64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.1.linux-arm64.tgz (SHA256) | |
| Mac (Experimental) | Intel | cockroach-v26.4.0-alpha.1.darwin-10.9-amd64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.1.darwin-10.9-amd64.tgz (SHA256) |
| ARM | cockroach-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) | Intel | cockroach-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 ... RENAMEandALTER PROCEDURE ... RENAMEnow require theCREATEprivilege on the schema containing the object, matching PostgreSQL behavior. Renames in thepublicschema are unaffected in the default configuration because all users haveCREATEon that schema.- Fixed a security issue with SAN-required client certificate authentication (
security.client_cert.san_required.enabled): if an HBA certificate rule omitted themapoption, 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 (mapon the certificate HBA rule configured withserver.identity_map.configuration) or an exact subject DN (theSUBJECTrole option); otherwise, the login is rejected. If you rely on SAN-required client cert auth, configure one of these bindings before upgrading. GROUP BYand a window’sORDER BYorPARTITION BYclause no longer accept an expression of a type that has no comparison operators, namelyrefcursor,jsonpath, and thetriggerpseudo-type. Such a query now returns the same “could not identify an ordering/equality operator” error that PostgreSQL returns, and that the equivalent statement-levelORDER BYalready returned. A query that relied on this must cast the expression to a comparable type (for exampleGROUP 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
ClientAuthenticationFailedevent to theSESSIONSlog channel with reasonUSER_NOT_FOUNDorLOGIN_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
LEAKPROOFuser-defined function to bypass row-level security (RLS). SettingLEAKPROOFviaCREATE FUNCTION,CREATE OR REPLACE FUNCTION, orALTER FUNCTIONnow requires membership in theadminrole;NOT LEAKPROOFis unchanged. ExistingLEAKPROOFfunctions are not modified. On upgrade, CockroachDB logs warnings for any existingLEAKPROOFUDFs owned by non-admin users so operators can review and, if needed, remove theLEAKPROOFdesignation. - 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_tokencondition and (when provided) the requiredscopeto request. Invalid SASL framing (e.g., unsupported channel binding data or a non-emptyauthzid) 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.enabledcluster 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-storeandPragma: no-cacheon 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-suitesflag, 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 STREAMnow requiresUSAGEon the external connection named as the source. Non-admin users must be grantedUSAGEon 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
USAGEprivilege on that external connection. This also applies to users with theCONTROLCHANGEFEEDrole option. EXPORTnow requires theUSAGEprivilege on an external connection named in its destination URI.ALTER BACKUPnow checks privileges on its collection URI, requiring theUSAGEprivilege when that URI names an external connection.- Starting or restarting Physical Cluster Replication (PCR) from an external connection now requires the
USAGEprivilege on that external connection. CREATE LOGICALLY REPLICATED TABLES ... WITH BIDIRECTIONAL ONnow reports a missingUSAGEprivilege 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_compactionnow requires theBACKUPsystem privilege, plus the same destination privileges asBACKUP(for example,EXTERNALIOIMPLICITACCESSfor implicitly authenticated destinations andUSAGEon external connections). These checks apply only to direct invocation of the built-in; compactions run via scheduled backups are unchanged. crdb_internal.backup_compactionnow requires theUSAGEprivilege 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 BACKUPandRESTOREnow require theUSAGEprivilege on an external connection named in a KMS URI. Existing backup schedules whose owner lacksUSAGEon a KMS external connection will fail until the grant is made. A schedule created withon_execution_failure = 'pause'must also be resumed withRESUME SCHEDULEonce the grant is in place.- The
cluster.secret,enterprise.license, andcloudstorage.http.custom_cacluster settings are now marked sensitive. Their values are redacted for users without theMODIFYCLUSTERSETTINGprivilege whenserver.redact_sensitive_settings.enabledis set, and are suppressed from diagnostics artifacts. Thesql.override.allow_unsafe_internals.enabledsetting 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 SETTINGevents 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
MODIFYCLUSTERSETTINGprivilege and even in debug zips collected without the--redactflag. Sensitive values are replaced with ‘<redacted>’. Privileged users can still read these values withSHOW CLUSTER SETTING. - The
set_cluster_settingandset_tenant_cluster_settingevents written tosystem.eventlogno longer record the values of sensitive cluster settings (such as authentication secrets). The event’s value field contains<redacted>instead; resets are still recorded asDEFAULT. - 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_settingsandsystem.eventlogdumps. 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--redactno longer contain the connection details of external connections or the execution arguments of scheduled jobs, both of which can hold cloud storage credentials. CREATE ROLEandALTER ROLEstatements 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--redactalso 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 clustersetting holds an unparsable certificate no longer includes the setting’s value. - Debug zips collected without
--redactand the output ofcockroach debug merge-logsno 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, andCREATE LOGICALLY REPLICATED. Such URIs now render as'*****'in contexts likeSHOW 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, andCREATE ROLE ... WITH PASSWORD). - Security improvement for replication statements: the source connection URI in
CREATE VIRTUAL CLUSTER ... FROM REPLICATIONandALTER VIRTUAL CLUSTER ... START REPLICATIONis now redacted by default in reformatted statement output, while job descriptions continue to display a sanitized URI. - Security improvement for
IMPORT ... AVRO: theschema_urioption is now redacted in formatted SQL output, and any secret query parameters inschema_uriare sanitized inIMPORTjob descriptions (e.g.,SHOW JOBS) to prevent leaking embedded cloud credentials.
General changes
CREATE CHANGEFEEDnow supports thecreate_kafka_topicsoption to control Kafka topic creation:broker_auto(default) relies on the Kafka cluster to auto-create topics,explicitcreates topics using the Kafka Admin API, andoffdisables topic creation.- The
admission.cpu_time_tokens.per_tenant.*metrics have been removed. Useadmission.cpu_time_tokens.{admitted_count,wait_time_nanos, tokens_used,tokens_returned}, labeled by (tenant_id,group_id), instead. - The
no-lingersink for changefeeds (the default for the kafka, webhook, and pubsub v2 sinks) no longer requiresFrequencywhenMessagesorBytesis set. The no-linger sink interprets theFlush.Frequencysink config option as a minimum linger; a batch is held until its oldest event is at leastFrequencyold, coalescing events into fewer, larger requests at the cost of latency, for examplekafka_sink_config='{"Flush": {"Frequency": "1s"}}'. Leave it unset for the lowest latency. - Changefeeds using
format=avrowith a schema registry now support anavro_modeoption. The default (avro_mode=write) preserves existing behavior by registering schemas with the registry. Settingavro_mode=readmakes 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_orderedoption to emit rows in non-decreasing updated-timestamp order. - Removed the
changefeed.new_kafka_sink.enabledcluster 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.enabledis enabled, a successful OAUTHBEARER authentication for a non-existent SQL user creates that user. The created role is marked with thePROVISIONSRCrole option set tooauth:<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 newavro_schemasoption lets you override subject names and select the registered version to use in read mode:latest(default),latest_compatible, orpin(<n>). Subject-name overrides also apply in the default write mode. CREATE LOGICAL REPLICATION STREAMandCREATE LOGICALLY REPLICATED TABLEnow accept aDLQ = <schema>(or<database>.<schema>) option withMODE = '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_subjectto 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 ANALYZEto 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. UpdatedEXPLAIN (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 ANALYZEto include KV read metrics from statements executed inside routine bodies (for example,PL/pgSQL), ensuring top-level statistics (such asrows decoded from KV) reflect the full work performed and are reported consistently. - Added a
query_tagscolumn tocrdb_internal.node_active_session_historyandcrdb_internal.cluster_active_session_historyto expose sqlcommenter query tags associated with each sampled statement, as a JSONB array of{name, value}objects. Populating this column requiressql.sqlcommenter.enabledandobs.ash.enrichment.query_tags.enabled(disabled by default). - Added a new
STATEMENTHINTSprivilege 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 requiringREPAIRCLUSTER. This privilege can be granted at the system level or per database;REPAIRCLUSTERcontinues to grant access for backward compatibility. - The
crdb_delete_statement_hintsandcrdb_enable_statement_hintsbuilt-ins now accept an optional database argument along with a hint row ID, allowing users with database-scopedSTATEMENTHINTSto manage individual statement hints. - Added
EXPLAIN ANALYZEexecution details for statements in the body ofPL/pgSQLsubroutines. - The
optimizer_use_routine_decorrelation_fixsession setting is now on by default in 26.3+. - Added the
optimizer_use_routine_decorrelation_fixsession 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 EXECUTEis now supported. It shows the query plan for a prepared statement with the specified parameters without executing it, matchingEXPLAINbehavior 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_fractioncluster setting (default0.05); set it to0to disable the index-scan path or1to always use a usable index. - Foreign key referential actions (for example,
ON DELETE CASCADEandON 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
SELECTandDELETEoperations as the TTL table’s owner instead of an internal superuser. As a result, any user-defined code invoked by TTL deletes (for example,DELETEtriggers) runs with the table owner’s privileges and seescurrent_useras the table owner. Row-level TTL still deletes expired rows even whenFORCE ROW LEVEL SECURITYwould hide them from the owner, or when the owner lacksEXECUTEprivileges on referenced functions. - Schema owners can now
DROP FUNCTIONandDROP PROCEDUREobjects in their schema, matching PostgreSQL behavior. - Added the
admission.kv.cpu_time_token_filler.dampening.enabledcluster setting, which lets operators disable runnable-goroutine-based dampening in the KV CPU time token filler. CREATE / ALTER / DROP / SHOW RESOURCE GROUPreturn an unimplemented error at plan time by default. Settingsql.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 forINSERT,UPDATE,DELETE, andUPSERTon 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_BuildAreaandST_ConcaveHullgeospatial functions. - Added the
disallow_ddl_in_explicit_transactionssession 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 withALTER ROLE ALL SET. ALTER TABLE ... ALTER COLUMN ... SET DATA TYPEoperations 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
REFERENCINGclause forCREATE TRIGGERis now supported. It allowsAFTERtriggers 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 byREFERENCING OLD TABLE ASandREFERENCING NEW TABLE AS. GRANTandREVOKEstatements that accidentally omit theSYSTEMkeyword (e.g.GRANT VIEWACTIVITY TO user) now include a hint in the error message directing the user to the correctGRANT 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 ANALYZEnow 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, andcpu_sql_nanos_sum_sqcolumns of theinformation_schema.crdb_statement_statisticsandinformation_schema.crdb_transaction_statisticsviews 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 ANALYZEnow 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_errguardrail 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, setsql.schema.validate_virtual_computed_columns.enabled(disabled by default). - The
ALTER TABLE ... AUDIT SETsyntax is now GA. The previousEXPERIMENTAL_AUDITkeyword is deprecated and will be removed in a future release. - Added two new
information_schemaviews,information_schema.crdb_statement_execution_insightsandinformation_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 TABLEwith storage parameters other than the row-level TTL family is now handled by the declarative schema changer.CREATE TABLEwith row-level TTL storage parameters is now handled by the declarative schema changer.- When
sql.procedures.plpgsql.late_binding.enabledis 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 atCALLtime. - The owner of a schema can now execute
DROP TYPEandDROP DOMAINon types and domains in that schema without owning the type itself, matching PostgreSQL.ALTER TYPE,ALTER DOMAIN, andCOMMENT ON TYPEstill require ownership of the type. - CockroachDB now supports
ALTER SCHEMA ... RENAME TOin 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, andcolumn_domain_usagetables are now populated.SHOW TYPESnow lists domain types in addition to enums and composite types, and includes a newcategorycolumn identifying the kind of each type.information_schema.columnsnow reports domain-typed columns using their base type fordata_typeandudt_namewhile identifying the domain in thedomain_catalog,domain_schema, anddomain_namecolumns. - The
information_schema.crdb_statement_statisticsandinformation_schema.crdb_transaction_statisticsviews now includesql_cpu_time_nanos_sumandsql_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_countcluster 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 VALUEnow supports theIF EXISTSclause, 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 forgen_random_uuid(). - The
information_schema.crdb_index_usage_statisticsview now includestotal_writesand last_write. - CockroachDB now supports the SQL/JSON
json_array()andjson_object()constructor functions from the SQL standard (as of PostgreSQL 16), including the{ NULL | ABSENT } ON NULL,{ WITH | WITHOUT } UNIQUE [ KEYS ], andRETURNINGclauses. For example,json_object('a' VALUE 1, 'b' VALUE 2)returns{"a": 1, "b": 2}. CREATE DOMAINandALTER DOMAINnow reject domain constraint names that match the reserved internal patterncrdb_internal_constraint_<id>_name_placeholder.- The
information_schema.crdb_index_usage_statisticsview now includesdatabase_name,schema_name,table_name, andindex_namecolumns (in addition totable_idandindex_id), allowing index usage statistics to be queried by object name without joiningcrdb_internalviews. IMPORT INTOnow supportsWITH 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_indexesview 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_activityview for inspecting persisted lock and latch contention with waiting and blocking statement attribution. DROP TYPE ... CASCADEis 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
EXECUTEnow supports aUSINGclause to bind values to$nplaceholders in the command string. - Added the
information_schema.crdb_databasesview 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 multiplecrdb_internaltables. - Added the
information_schema.crdb_tablesview 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-NULLinput value (orNULLif all inputs areNULL) and can also be used as a window function.
Operational changes
- Added twelve
server.oauthbearer_authentication.*cluster settings for configuring SASLOAUTHBEARERauthentication. - 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.countand their.internalcounterparts 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 thesql.misc.*.countseries 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, andoverhead_k, to help investigate allocator-related CPU usage. - Reduced the default value of the
kv.range_merge.queue_intervalcluster 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_levelmetric, 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.enabledconfig property, which is recommended to meet data domiciling requirements if you use theSTRICToption withBACKUP. - Execution insights are now periodically persisted to the
system.statement_execution_insightsandsystem.transaction_execution_insightstables, providing a durable, cluster-wide record that survives node restarts and outlives the in-memory window. Persistence is controlled by the newsql.insights.flush.enabled(defaulttrue),sql.insights.flush.interval(default10m),sql.insights.flush.jitter(default0.15), andsql.insights.flush.batch_size(default100) cluster settings. - Added the
admission.kv.cpu_time_token_filler.dampening.enabledcluster 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, andsql.txn.count.read_committed. On the Prometheus/metricsendpoint, these are exposed as a singlesql.txn.countmetric labeled byisolation_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
sqlCPUTimeNanosin thecrdb_internal.statement_statisticsandcrdb_internal.transaction_statisticstables, 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_usedmetric 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.countmetric 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 insql.failure.count, alongsidesql.statement_timeout.countandsql.transaction_timeout.count. - Added the
sql.schema_changer.index_backfill_version_barrier.enabledcluster setting (defaulttrue). 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, hardeningALTER PRIMARY KEYrun 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 tofalseto 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.capacitycluster setting:sql.table_statistics.cache.hitsand.missescount lookup outcomes;sql.table_statistics.cache.evictions.capacityand.evictions.invalidatedcount evictions split by cause;sql.table_statistics.cache.eviction_idle_durationrecords 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); andsql.table_statistics.cache.entriesand.mem_bytesreport 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_TIMEOUTenvironment 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 theCOCKROACH_TLS_HANDSHAKE_TIMEOUTenvironment variable. - Breaking change: Removed the deprecated
IMPORTandRESTOREevent logs. Use the job status change event logs instead. - The
obs.ash.enrichment.enabledcluster setting now defaults totrue. 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 ofcrdb_internal.node_active_session_historyandcrdb_internal.cluster_active_session_historyare populated without further configuration. Enrichment additionally requires the cluster version to be finalized; until then these columns remainNULL. Set the setting tofalseto 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 thebackup_typelabel) for backup schedules configured with theupdates_cluster_last_backup_time_metricoption. 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, anddistsender.rangecache.evictions.stale. - Added the
obs.ash.labels.kv_batch_key.enabledcluster setting (default off). When enabled together withobs.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. Thecrdb_internal.key_to_table_idandcrdb_internal.key_to_table_index_idbuiltins now also accept the pretty-printed key string form stored in these labels. - Added the
obs.ash.labels.kv_sync_wait.enabledcluster 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 bothobs.ash.labels.enabledandobs.ash.labels.kv_sync_wait.enabledare set totrue. Both settings default tofalse. - Renamed metric
schedules.BACKUP.cluster.time_since_last_completedtoschedules.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 theupdates_cluster_last_backup_time_metricschedule option is enabled. - Removed the
schedules.backup.gc_protection.enabledcluster 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.enabledenables KV nodes to buffer KV ASH samples for tenants to pull, andobs.ash.kv_sample_egress.per_tenant_capacity/obs.ash.kv_sample_egress.total_capacitycontrol per-tenant and total retained sample capacity. - The
/debug/lsmendpoint, 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.*andstorage.*) 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>.localand<name>.shared, exported as the<name>.by-enginefamily with anenginelabel. On clusters using range-shared engines,rocksdb.read-amplificationandrocksdb.level-scoreare now the mean across a store’s engines rather than the store-local engine’s value;rocksdb.read-amplification.localandrocksdb.level-score.localreport what those metrics reported before. - The
changefeed.mvcc_ordered_buffer.bytesmetric tracks the total memory and disk usage inordered_bufferwhenmvcc_orderedis enabled on sinkless feeds. - Added
basalt.fs.quorum_write.*andbasalt.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 sqlCLI now supports interactive OAuth login using the OAuth 2.0 device authorization grant. Configure--oauth-issuerand--oauth-client-id(optionally--oauth-scope) to open a browser for authentication and connect using the resulting token. For security, the SQL connection must usesslmode=verify-fulland the issuer must usehttps; for local testing with a non-HTTPS issuer, setCOCKROACH_OAUTH_ALLOW_INSECURE_ISSUERto relax only the issuer requirement. - The
cockroach debug encryption-status,cockroach debug encryption-registry-list, andcockroach debug encryption-decryptcommands 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-dirfor the cluster key). The store must be offline. - The
cockroach debug pebblesubcommands now take the target database directory and files using the--dirand--fileflags 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.enabledcluster 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.cooldowncluster 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
diffenabled, or a CDC query usingcdc_prev, to fail with a GC threshold error if garbage collection ran during the scan. - Fixed a bug where
CREATE TEMPORARY TABLEcould 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, andsource.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_sizeoption be increased. - Fixed a bug where
DISTINCT ONqueries withORDER BYcould 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-tracecould 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 SCHEMAwith 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 FULLforeign 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
EXPLAINorEXPLAIN ANALYZEstatement 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 thesql.txn.contended.countmetric 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 issuingROLLBACK 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_recscould 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.leasecontained 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 namedindex, 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 decommissionpre-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
CHANGEFEEDto emit an incorrectprev_valuewhen thedisable_changefeed_replicationoption 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_lockorpg_advisory_xact_lock_sharedcould 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 ... INTOstatement that also performed anINSERT,UPDATE, orDELETE. - 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_hintsdid 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 correspondingcrdb_internalvirtual 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,
IMPORTandRESTORE) 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-responseandkv-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.leasefor as long as the owning node stayed up. The stale row could cause schema changes (such asDROP TABLEorDROP DATABASE) on that descriptor to hang indefinitely until the node holding the stale lease was restarted. - Fixed a bug where an
ALTER PRIMARY KEYon aREGIONAL BY ROWtable 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_localityoption 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 ANALYZEnow 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 ANALYZEcould 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 initto be refused. Such a store is now correctly treated as uninitialized; the partially written store must be cleared beforecockroach initcan be retried. CREATE TENANTnow fails with a clear error if theRANGE tenantszone configuration is invalid, instead of creating a tenant that cannot finish starting up.ALTER RANGE default ... CONFIGURE ZONEnow rejects a change that would make an inheriting named range (such asRANGE tenants) invalid, instead of silently producing an invalid inherited configuration.- An
INSERTorUPDATEthat writes the referencing columns of a foreign key no longer requires the writing user to hold theSELECTprivilege on the referenced table, matching PostgreSQL. The foreign-key existence check is authorized by the constraint itself, whose creation already required theREFERENCESprivilege on the referenced table. - Fixed a bug where
ALTER RANGE ... RELOCATEandALTER RANGE ... RELOCATE LEASEloaded 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 concurrentRELOCATEstatements 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
CONTEXTreporting, matching PostgreSQL. - Fixed an internal error (“inconsistent Case return types”) that could occur when a
CASEexpression referenced a column produced by unnesting a constant array whose only element was a typedNULL, such asunnest(ARRAY[NULL]::TEXT[]). - Fixed a bug where the
chunk_sizeoption toEXPORT INTO PARQUETwas ignored, so files were rotated only bychunk_rows.EXPORTnow bounds the approximate size of each parquet file as documented. - Fixed an internal error “inconsistent Case return types” that could occur when an
IFERRORexpression with aNULLfirst argument was used as a branch of aCASEexpression. - Fixed an internal error (“inconsistent Case return types”) that could occur for
CASE,IF, orNULLIFexpressions when one branch was constant-folded toNULL. In addition,CASEandIFexpressions 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-suitesflag) 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 newoptimizer_max_disjunction_split_countsession variable. - Errors with uncategorized
SQLSTATEcodes and retryable errors in PL/pgSQL blocks with non-matching exception handlers now include the PostgreSQL-compatibleCONTEXTfield 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_bytesandcloud.write_bytesmetrics 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_timeoutsession 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 DATAand plainCREATE TABLEremain 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
OFFSETcould incorrectly return an empty result instead of an error when thetransaction_rows_read_errsession 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 BACKUPSwould 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_COMMITTEDwhen 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 andDROP TABLEto fail with an internal error. - Fixed a bug where using
FETCH ABSOLUTEon 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-waterafter being replanned (for example, after changing its sink destination via an external connection). - Fixed a bug where a failed
ALTER DOMAIN ... SET DEFAULTorALTER DOMAIN ... DROP DEFAULTcould 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
NAMEcolumn compared to a string literal) and a type-sensitive expression such aspg_typeofwas 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 KEYcould 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 aNULLelement. - 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 DEFINERoption 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 declaredSECURITY DEFINERnow execute as the function owner, matching PostgreSQL, socurrent_userand privilege checks inside the trigger body resolve to the owner. - Fixed an internal error when a
CREATE DOMAINstatement’sCHECKconstraint contained a subquery. DomainCHECKconstraints containing subqueries or aggregate, window, set-returning, or procedure calls are now rejected byCREATE DOMAINandALTER DOMAINinstead of being accepted and failing later. - Fixed a bug where preparing
EXECUTE pand then re-preparingpwith a different set of result columns caused an internal error. CockroachDB now returns the expectedcached plan must not change result typeerror. - Fixed a bug in the declarative schema changer where
DROP INDEXcould fail with a spuriouscannot drop index ... because <function/view> depends on iterror 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
RESTOREwith theskip_missing_sequencesoption could fail with an internal validation error when a column’sDEFAULTexpression 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_corruptionsreported a session’s temporary schema as corruption andcrdb_internal.repair_catalog_corruptiondeleted 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_argumentsorpg_get_function_identity_argumentson 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, orSHOW QUERIEScould 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
INSERTstatements with generated primary keys. - Fixed a bug where some queries involving the
triggerpseudo-type (for example, via thetrigger_inbuiltin) 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_pathcould 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) inenv.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_locksandcrdb_internal.cluster_held_advisory_lockscould report a transaction-scoped advisory lock as held after a statement in aREAD COMMITTEDtransaction 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
TIMESTAMPTZcolumn with aTIMESTAMPorDATEconstant 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
INTcolumn to aFLOATconstant 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
RESTOREthat 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 asrestoring 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 STATISTICSstatements could appear to hang before surfacing their error. - Fixed a bug where
BACKUPandRESTOREof an individual table with a column of a user-definedDOMAINtype 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 withunable to coerce type <t> to anyelementwhen 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
DOMAINtype used aCHECKconstraint containing a range condition. - Fixed a bug where
TSVECTORorTSQUERYvalues 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, duringEXPORTfollowed byIMPORT). - Fixed a bug where
crdb_internal.sstable_metricscould ignore itsend_keyargument 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 CURSORstatement in an explicitREAD COMMITTEDtransaction was automatically retried (for example, after a transaction conflict). - Fixed a bug that could cause queries with inequality predicates (for example,
!= 'null') on aJSONBcolumn in a forward (non-inverted) index to silently miss rows where the JSONB value was an empty array ([]). - Fixed a bug where
SHOW PARTITIONSand other queries that look up rows incrdb_internal.table_indexesby 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-keyreportedPlaintextfor 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
ENUMprefix 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_countsession setting. - Fixed a compatibility issue where
BACKUP,RESTORE, andSHOW BACKUPScould fail against some S3-compatible object stores that require single-character delimiters when listing objects (for example, Alibaba OSS). - Fixed a bug where
CREATE TRIGGERspecifying 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 typetrigger. - 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_timeoutinside an explicit transaction could leave the transaction in an unrecoverable aborted state. Explicit transactions can now be recovered withROLLBACK 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 diffcould emit confusing delete messages with both before and after images set toNULL. This could occur onREGIONAL BY ROWtables underREAD COMMITTEDorSNAPSHOTisolation, 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-LOCKfile 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 acceptNULLelements in thethresholdsarray and return an incorrect bucket index. It now returns an error (thresholds array must not contain NULLs) ifthresholdscontains anyNULL, matching PostgreSQL behavior. - Fixed a bug where
make_date(),make_timestamp(), andmake_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-headerscaused it to reject connections that did not begin with a PROXY protocol header. Nodes now accept direct connections (for example, health probes andcockroach init) and honor the PROXY header only when it is present.
Performance improvements
SHOW CHANGEFEED JOBSis now significantly faster and uses less temporary storage when listing changefeeds that watch many tables.- Improved performance for some correlated
EXISTSandINsubqueries that includeUNION 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_statementson 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_countcluster setting. When set above1, 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 to0(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_optionstable to evaluate theBYPASSRLSexemption, adding a round-trip (potentially cross-region, sincesystem.role_optionsis 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.namespacefor 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.concurrencycluster 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 constantLIMITby 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 onARRAYandSTRINGcolumns in the index recommendation engine, improving recommendations for queries that use array containment operators (such as@>and<@) andLIKE/ILIKEpredicates. - 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 COPYnow outputs the same 4 column result as traditional restore.RESTORE ... WITH EXPERIMENTAL DEFERRED COPYkeeps 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, 2026Downloads
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 System | Architecture | Full executable | SQL-only executable |
|---|---|---|---|
| Linux | Intel | cockroach-v26.4.0-alpha.2.linux-amd64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.2.linux-amd64.tgz (SHA256) |
| ARM | cockroach-v26.4.0-alpha.2.linux-arm64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.2.linux-arm64.tgz (SHA256) | |
| Mac (Experimental) | Intel | cockroach-v26.4.0-alpha.2.darwin-10.9-amd64.tgz (SHA256) | cockroach-sql-v26.4.0-alpha.2.darwin-10.9-amd64.tgz (SHA256) |
| ARM | cockroach-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) | Intel | cockroach-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_MARKERflag.
Security updates
- Redacted secret values for changefeed schedule options (for example,
webhook_auth_header) in thecommandcolumn ofSHOW SCHEDULES, in addition to sanitizing the sink URI. - The values of the changefeed options
webhook_auth_header,extra_headers, andconfluent_schema_registry, which can contain credentials, are now redacted by default when a changefeed statement is reformatted for display (e.g. inSHOW CREATE SCHEDULE), matching the existing handling of changefeed sink URIs.
General changes
- Changed the default value of the
sql.insights.anomaly_detection.memory_limitcluster setting to10MiB(from1MiB), 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.enabledset, 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.enabledto 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 incrementjobs.execution.panics_recoveredand should be restarted.
SQL language changes
- Fixed a bug where
LOOKUP JOINorMERGE JOINhints 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_limitsession 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 TABLEandINSPECT DATABASE; selecting a partial index with theINDEXoption no longer returns an error. SHOW CREATE TABLEnow lists a column family’s members in column-ID order for tables created after this change, rather than in the order theFAMILYclause named them. Families of existing tables are unaffected, and generated family names are unchanged.- Added the
information_schema.crdb_storesview to list per-store metrics (includingnode_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 ofcrdb_internal.kv_store_status. This view is not supported in secondary tenants. CREATE TEMPORARY TABLEnow supports the PostgresON COMMIT DELETE ROWSandON COMMIT DROPoptions, in addition to the existingON COMMIT PRESERVE ROWSdefault.ON COMMIT DELETE ROWSremoves all rows at the end of every successful transaction.ON COMMIT DROPdrops the table when its creating transaction commits. Temporary tables remain gated by theexperimental_enable_temp_tablessession setting. Whenautocommit_before_ddlis enabled,CREATE TEMPORARY TABLE ... ON COMMIT DROPitself is exempt, but other DDL can still commit the transaction and drop the temporary table before that statement runs.- Changed
IMPORT INTOforREGIONAL BY TABLEtables to defaultexecution_localityto the table’s home region when the option is not specified, which can reduce cross-region traffic. Setexecution_locality = ''to opt out and run unconstrained. - Implemented the
ST_ForceRHR(geometry)builtin function, a synonym ofST_ForcePolygonCWthat 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.enabledenables or disables pulling KV-side ASH samples into the tenant.obs.ash.kv_sample_pull.intervalsets how frequently the tenant pulls KV-side ASH samples. - Added the
sql.routine.dynamic_execute.started.countandsql.routine.dynamic_execute.countmetrics, which count statements run through a PL/pgSQL dynamicEXECUTE. - Changed routine statement metrics so SQL statements executed via PL/pgSQL
EXECUTEare now counted in the correspondingsql.routine.<type>.countmetrics (forSELECT,INSERT,UPDATE, andDELETE), and are also tracked separately in the newsql.routine.dynamic_execute.*metrics. - Updated the
--external-io-dirhelp text to clarify that passing an explicitly empty value (--external-io-dir=) disables local file I/O, and thatdisabledis 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
TRUNCATEcould incorrectly treat indexes backingUNIQUEconstraints as explicitly created, allowingDROP INDEXto drop them without requiringCASCADE. - 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 VALUEcould succeed even when the enum value was referenced as an explicitly typed constant in a triggerWHENcondition or trigger function body. This could leave the trigger in an invalid state and cause subsequentINSERT,UPDATE, andDELETEstatements on the table to fail;ALTER TYPE ... DROP VALUEnow 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
IMPORTprogress tracking that could compute an incorrect resume position, causing some rows to be skipped when anIMPORTjob was resumed. - Fixed a bug where sessions with
default_int_size=4could have unqualifiedINTEGERtypes re-resolved asINT8during 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
tsquerymatch) could cause the node to run out of memory during query planning. Such filters now respect theoptimizer_span_limitsession 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 EncDatumafter anINTERVALoverflow 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.enabledcluster 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
EXCEPTIONhandler could be matched to the wrong enclosingEXCEPTIONclause, 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 toREGIONAL BY TABLE IN <region>viaALTER TABLE ... LOCALITYin 26.2+. pg_catalog.pg_dependreported the wrong column for a view depending on a column whose type had been changed by anALTER COLUMN TYPEthat rewrote on-disk data.- Foreign key, check, unique, and
NOT NULLconstraints on a column whose type had been changed by anALTER COLUMN TYPEthat rewrote on-disk data were not visible to tools that inspect constraints throughpg_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 inpg_catalog) when the column was compared to an integer constant or parameter (for example, a client driver binding the value asint4orint8), which could cause a full table scan.

