New limitations
Limitations for EXPLAIN ANALYZE
- does not collect inverted statistics on columns that are indexed with both forward and inverted indexes; only forward statistics are collected for those columns.
-
does not support the
AS OF SYSTEM TIMEsyntax. Use instead.
Limitations for index recommendations
- recommendations are not aware of .
- CockroachDB does not support recommendations on .
Limitations for SELECT FOR UPDATE
- places locks on each key scanned by the base index scan. This means that even if some of those keys are later filtered out by a predicate which could not be pushed into the scan, they will still be locked.
- only places an unreplicated lock on the index being scanned by the query. This diverges from PostgreSQL, which aquires a lock on all indexes.
Limitations for composite types
- Changefeed types are not fully integrated with . Running changefeeds with user-defined composite types is in . Certain changefeed types do not support user-defined composite types. Refer to the change data capture for more detail. The following limitations apply:
- A changefeed in will not be able to serialize .
- A changefeed emitting will include
ASlabels in the message format when the changefeed serializes a .
Common table expressions are not supported in user-defined functions
(CTE), recursive or non-recursive, are not supported in (UDF). That is, you cannot use aWITH clause in the body of a UDF.
Low estimated Request Units are rounded to zero
The (RUs) estimate surfaced in is displayed as an integer value. Because of this, fractional RU estimates, which represent very inexpensive queries, are rounded down to zero.AS OF SYSTEM TIME does not support placeholders
CockroachDB does not support placeholders in . The time value must be embedded in the SQL string.
null_ordered_last does not produce correct results with tuples
By default, CockroachDB orders NULLs before all other values. For compatibility with PostgreSQL, the null_ordered_last was added, which changes the default to order NULLs after all other values. This works in most cases, due to some transformations CockroachDB makes in the optimizer to add extra ordering columns. However, it is broken when the ordering column is a tuple.
Inverted join for tsvector and tsquery types is not supported
CockroachDB cannot index-accelerate queries with @@ predicates when both sides of the operator are variables.
No guaranteed state switch from DECOMMISSIONING to DECOMMISSIONED if node decommission is interrupted
There is no guaranteed state switch from DECOMMISSIONING to DECOMMISSIONED if is interrupted in one of the following ways:
- The
cockroach node decommission --wait-allcommand was run and then interrupted - The
cockroach node decommission --wait=nonecommand was run
--wait=none is used, the state will only flip to “decommissioned” when the CLI program is run again after decommissioning has done all its work.
Execution locality in changefeeds
- Changefeeds that use the set to a could create a plan that assigns most of the ranges to an on the coordinator node. This leads to an unbalanced plan and slow changefeed progress, particularly when the table is large and has many ranges.
Unresolved limitations
Limitations for user-defined functions (UDFs)
Limitations on use of UDFs
are not currently supported in:- Expressions (column, index, constraint) in tables.
- Views.
- Other user-defined functions.
Limitations on expressions allowed within UDFs
The following are not currently allowed within the body of a :-
Mutation statements such as
INSERT,UPDATE,DELETE, andUPSERT. - Common table expressions (CTEs).
- References to other user-defined functions.
Table-level restore will not restore user-defined functions
RESTORE will not restore a table that references a , unless you skip restoring the function with the skip_missing_udfs option. Alternatively, take a to include everything needed to restore the table.
Incorrect query plans for partitions with NULL values
In cases where the partition definition includes a comparison with NULL and a query constraint, incorrect query plans are returned. However, this case uses non-standard partitioning which defines partitions which could never hold values, so it is not likely to occur in production environments.
Limitations for DROP OWNED BY
drops all owned objects as well as any on objects not owned by the .
DROP OWNED BY is not supported where role has system-level privileges
-
If the for which you are trying to
DROP OWNED BYwas granted a (i.e., using the statement), the error shown below will be signalled. The workaround is to use and then use for each privilege in the result.
Spatial features disabled for ARM Macs
are disabled due to an issue with macOS code signing for the GEOS libraries. Users needing spatial features on an ARM Mac may instead use Rosetta to or use the distribution. This is expected to be resolved in an upcoming 22.2 patch release.Limited SQL cursor support
CockroachDB implements SQL cursor support with the following limitations:DECLAREonly supports forward cursors. Reverse cursors created withDECLARE SCROLLare not supported.FETCHsupports forward, relative, and absolute variants, but only for forward cursors.BINARY CURSOR, which returns data in the Postgres binary format, is not supported.WITH HOLD, which allows keeping a cursor open for longer than a transaction by writing its results into a buffer, is accepted as valid syntax within a single transaction but is not supported. It acts as a no-op and does not actually perform the function ofWITH HOLD, which is to make the cursor live outside its parent transaction. Instead, if you are usingWITH HOLD, you will be forced to close that cursor within the transaction it was created in.-
This syntax is accepted (but does not have any effect):
-
This syntax is not accepted, and will result in an error:
-
This syntax is accepted (but does not have any effect):
- Scrollable cursor (also known as reverse
FETCH) is not supported. - with a cursor is not supported.
- Respect for is not supported. Cursor definitions do not disappear properly if rolled back to a
SAVEPOINTfrom before they were created.
SELECT FOR UPDATE locks are dropped on lease transfers and range splits/merges
Locks acquired using SELECT ... FOR UPDATE are dropped on and . SELECT ... FOR UPDATE locks should be thought of as best-effort, and should not be relied upon for correctness, as they are implemented as fast, in-memory .
If a lease transfer or range split/merge occurs on a range held by an unreplicated lock, the lock is dropped, and the following behaviors can occur:
- The desired ordering of concurrent accesses to one or more rows of a table expressed by your use of
SELECT ... FOR UPDATEmay not be preserved (that is, a transaction B against some table T that was supposed to wait behind another transaction A operating on T may not wait for transaction A). - The transaction that acquired the (now dropped) unreplicated lock may fail to commit, leading to .
Unsupported trigram syntax
The following PostgreSQL syntax and features are currently unsupported for :word_similarity()built-in function.strict_word_similarity()built-in function.%>and<%comparisons and acceleration.<<%and%>>comparisons and acceleration.<->,<<->,<->>,<<<->, and<->>>comparisons.- Acceleration on .
%comparisons,show_trgm, and trigram index creation on .
A multi-region table cannot be restored into a non-multi-region table
You cannot a multi-region table into a non-multi-region table.Statements containing multiple modification subqueries of the same table are disallowed
Statements containing multiple modification subqueries mutating the same row could cause corruption. These statements are disallowed by default, but you can enable multiple modification subqueries with one the following:- Set the
sql.multiple_modifications_of_table.enabledtotrue. - Use the
enable_multiple_modifications_of_table.
ON CASCADE clauses between them, the results will be different from what is expected in PostgreSQL.
transaction_rows_read_err and transaction_rows_written_err do not halt query execution
The transaction_rows_read_err and transaction_rows_written_err limit the number of rows read or written by a single . These session settings will fail the transaction with an error, but not until the current query finishes executing and the results have been returned to the client.
sql.guardrails.max_row_size_err misses indexed virtual computed columns
The sql.guardrails.max_row_size_err misses large rows caused by indexed virtual computed columns. This is because the guardrail only checks the size of primary key rows, not secondary index rows.
CockroachDB does not allow inverted indexes with STORING
CockroachDB does not allow inverted indexes with a .
CockroachDB does not properly optimize some left and anti joins with GIN indexes
and anti joins involving , , or columns with a multi-column or will not take advantage of the index if the prefix columns of the index are unconstrained, or if they are constrained to multiple, constant values. To work around this limitation, make sure that the prefix columns of the index are either constrained to single constant values, or are part of an equality condition with an input column (e.g.,col1 = col2, where col1 is a prefix column and col2 is an input column).
For example, suppose you have the following and tables:
t1 and t2 on only the geometry columns, CockroachDB will not be able to plan an :
crdb_region column to a single value, CockroachDB can plan an inverted join:
Using RESTORE with multi-region table localities
- Restoring and tables into a non-multi-region database is not supported.
-
and tables can be restored only if the regions of the backed-up table match those of the target database. All of the following must be true for
RESTOREto be successful:- The of the source database and the regions of the destination database have the same set of regions.
- The regions were added to each of the databases in the same order.
- The databases have the same .
Running on the destination database:In addition, the following scenario has mismatched regions between the databases since the regions were not added to the database in the same order. Running on the source database:Running on the destination database:
SET does not ROLLBACK in a transaction
SET does not properly apply within a transaction. For example, in the following transaction, showing the TIME ZONE does not return 2 as expected after the rollback:
JSONB/JSON comparison operators are not implemented
You cannot use comparison operators (such as < or >) on elements. For example, the following query does not work and returns an error:
Locality-optimized search works only for queries selecting a limited number of records
- Locality optimized search works only for queries selecting a limited number of records (up to 100,000 unique keys).
Expression indexes cannot reference computed columns
CockroachDB does not allow expression indexes to reference .Materialized view limitations
- The optimizer may not select the most optimal query plan when querying materialized views because CockroachDB does not on materialized views.
-
CockroachDB cannot refresh materialized views inside . Trying to refresh a materialized view inside an explicit transaction will result in an error.
-
Start with the sample
bankdata set: - Create the materialized view described in .
-
Start a new multi-statement transaction with :
-
Inside the open transaction, attempt to . This will result in an error.
-
Start with the sample
CockroachDB cannot plan locality optimized searches that use partitioned unique indexes on virtual computed columns
- Locality optimized search does not work for queries that use on . A workaround for computed columns is to make the virtual computed column a . Locality optimized search does not work for queries that use partitioned unique .
Expressions as ON CONFLICT targets are not supported
CockroachDB does not support expressions as ON CONFLICT targets. This means that unique expression indexes cannot be selected as arbiters for statements. For example:
Statistics limitations
- The automatically checks whether it needs to refresh statistics for every table in the database upon startup of each node in the cluster. If statistics for a table have not been refreshed in a while, this will trigger collection of statistics for that table. If statistics have been refreshed recently, it will not force a refresh. As a result, the automatic statistics refresher does not necessarily perform a refresh of statistics after an . This could cause a problem, for example, if the upgrade moves from a version without to a version with histograms. To refresh statistics manually, use .
-
The following do not immediately take effect, and instead only take effect when new statistics are collected for a table.
-
When a table is dropped, the related rows in
system.table_statisticsare not deleted. CockroachDB does not delete historical statistics. - CockroachDB does not collect statistics for . This can prevent the from accurately calculating the cost of scanning an index on a virtual column, and, transitively, the cost of scanning an .
Differences in syntax and behavior between CockroachDB and PostgreSQL
CockroachDB supports the PostgreSQL wire protocol and the majority of its syntax. However, CockroachDB does not support some of the PostgreSQL features or behaves differently from PostgreSQL because not all features can be easily implemented in a distributed system. For a list of known differences in syntax and behavior between CockroachDB and PostgreSQL, see .Multiple arbiter indexes for INSERT ON CONFLICT DO UPDATE
CockroachDB does not currently support multiple arbiter indexes for , and will return an error if there are multiple unique or exclusion constraints matching the ON CONFLICT DO UPDATE specification.
Spatial support limitations
CockroachDB supports efficiently storing and querying , with the following limitations:- Not all PostGIS spatial functions are supported.
-
The
AddGeometryColumnonly allows constant arguments. -
The
AddGeometryColumnspatial function only allows thetruevalue for itsuse_typmodparameter. -
CockroachDB does not support the
@operator. Instead of using@in spatial expressions, we recommend using the inverse, with~. For example, instead ofa @ b, useb ~ a. -
CockroachDB does not yet support s into the . This limitation also blocks the
ogr2ogr -f PostgreSQLfile conversion command. -
CockroachDB does not yet support Triangle or
TINspatial shapes. - CockroachDB does not yet support Curve, MultiCurve, or CircularString spatial shapes.
- CockroachDB does not yet support k-nearest neighbors.
-
CockroachDB does not support using to refer to with type modifiers (e.g.,
public.geometry(linestring, 4326)). Instead, use fully-unqualified names to refer to data types with type modifiers (e.g.,geometry(linestring,4326)). Note that, in output, data type names are prefixed bypublic.. If the type has a type modifier, you must remove thepublic.from the type name in order for the statements to work in CockroachDB.
Enterprise BACKUP does not capture database/table/column comments
The statement associates comments to databases, tables, or columns. However, the internal table (system.comments) in which these comments are stored is not captured by a of a table or database.
As a workaround, take a cluster backup instead, as the system.comments table is included in cluster backups.
SHOW BACKUP does not support symlinks for nodelocal
does not support listing backups if the storage location is a symlink.
DB Console may become inaccessible for secure clusters
Accessing the DB Console for a secure cluster now requires login information (i.e., username and password). This login information is stored in a system table that is replicated like other data in the cluster. If a majority of the nodes with the replicas of the system table data go down, users will be locked out of the DB Console.Large index keys can impair performance
The use of tables with very large primary or secondary index keys (>32KB) can result in excessive memory usage. Specifically, if the primary or secondary index key is larger than 32KB the default indexing scheme for SSTables breaks down and causes the index to be excessively large. The index is pinned in memory by default for performance. To work around this issue, we recommend limiting the size of primary and secondary keys to 4KB, which you must account for manually. Note that most columns are 8B (exceptions beingSTRING and JSON), which still allows for very complex key structures.
Using LIKE...ESCAPE in WHERE and HAVING constraints
CockroachDB tries to optimize most comparisons operators in WHERE and HAVING clauses into constraints on SQL indexes by only accessing selected rows. This is done for LIKE clauses when a common prefix for all selected rows can be determined in the search pattern (e.g., ... LIKE 'Joe%'). However, this optimization is not yet available if the ESCAPE keyword is also used.
Current sequence value not checked when updating min/max value
Altering the minimum or maximum value of a series does not check the current value of a series. This means that it is possible to silently set the maximum to a value less than, or a minimum value greater than, the current value.Using default_int_size session variable in batch of statements
When setting the default_int_size in a batch of statements such as SET default_int_size='int4'; SELECT 1::IN, the default_int_size variable will not take affect until the next statement. This happens because statement parsing takes place asynchronously from statement execution.
As a workaround, set default_int_size via your database driver, or ensure that SET default_int_size is in its own statement.
COPY syntax not supported by CockroachDB
CockroachDB does not yet support the following COPY syntax:
- Various
COPYoptions (FORMAT,FREEZE,QUOTE, etc.). COPY ... FROM ... WHERE <expr>.
Import with a high amount of disk contention
can sometimes fail with a “context canceled” error, or can restart itself many times without ever finishing. If this is happening, it is likely due to a high amount of disk contention. This can be mitigated by setting thekv.bulk_io_write.max_rate to a value below your max disk write speed. For example, to set it to 10MB/s, execute:
Placeholders in PARTITION BY
When defining a , either during table creation or table alteration, it is not possible to use placeholders in the PARTITION BY clause.
Dropping a single partition
CockroachDB does not currently support dropping a single partition from a table. In order to remove partitions, you can the table.Adding a column with sequence-based DEFAULT values
It is currently not possible to to a table when the column uses a as the value, for example:
Available capacity metric in the DB Console
If you are testing your deployment locally with multiple CockroachDB nodes running on a single machine (this is ), you must explicitly per node in order to display the correct capacity. Otherwise, the machine’s actual disk capacity will be counted as a separate store for each node, thus inflating the computed capacity.Schema changes within transactions
Within a single :- You can run schema changes inside the same transaction as a statement. For more information, see . However, a
CREATE TABLEstatement containing clauses cannot be followed by statements that reference the new table. - Schema change DDL statements inside a multi-statement transaction can fail while other statements succeed.
- can result in data loss if one of the other schema changes in the transaction fails or is canceled. To work around this, move the
DROP COLUMNstatement to its own explicit transaction or run it in a single statement outside the existing transaction.
If a schema change within a transaction fails, manual intervention may be needed to determine which statement has failed. After determining which schema change(s) failed, you can then retry the schema change.
Schema change DDL statements inside a multi-statement transaction can fail while other statements succeed
Most schema change DDL statements that run inside a multi-statement transaction with non-DDL statements can fail at time, even if other statements in the transaction succeed. This leaves such transactions in a “partially committed, partially aborted” state that may require manual intervention to determine whether the DDL statements succeeded. Some DDL statements do not have this limitation.CREATE TABLE and CREATE INDEX statements have the same atomicity guarantees as other statements within a transaction.
If such a failure occurs, CockroachDB will emit a CockroachDB-specific error code, XXA00, and the following error message:
If you must execute schema change DDL statements inside a multi-statement transaction, we strongly recommend checking for this error code and handling it appropriately every time you execute such transactions.
- Creating a unique index fails because values aren’t unique.
- The evaluation of a computed value fails.
- Adding a constraint (or a column with a constraint) fails because the constraint is violated for the default/computed values in the column.
t and seeing that the additional non-unique value 3 was successfully inserted.
Schema changes between executions of prepared statements
When the schema of a table targeted by a prepared statement changes after the prepared statement is created, future executions of the prepared statement could result in an error. For example, adding a column to a table referenced in a prepared statement with aSELECT * clause will result in an error:
SELECT * in prepared statements, when possible.
Size limits on statement input from SQL clients
CockroachDB imposes a hard limit of 16MiB on the data input for a single statement passed to CockroachDB from a client (including the SQL shell). We do not recommend attempting to execute statements from clients with large input.Using \| to perform a large input in the SQL shell
In the , using the operator to perform a large number of inputs from a file can cause the server to close the connection. This is because \| sends the entire file as a single query to the server, which can exceed the upper bound on the size of a packet the server can accept from any client (16MB).
As a workaround, with cat data.sql | cockroach sql instead of from within the interactive shell.
New values generated by DEFAULT expressions during ALTER TABLE ADD COLUMN
When executing an statement with a expression, new values generated:
- use the default regardless of the search path configured in the current session via
SET SEARCH_PATH. - use the UTC time zone regardless of the time zone configured in the current session via .
- have no default database regardless of the default database configured in the current session via , so you must specify the database of any tables they reference.
- use the transaction timestamp for the
statement_timestamp()function regardless of the time at which theALTERstatement was issued.
Load-based lease rebalancing in uneven latency deployments
When nodes are started with the flag, CockroachDB attempts to place the replica lease holder (the replica that client requests are forwarded to) on the node closest to the source of the request. This means as client requests move geographically, so too does the replica lease holder. However, you might see increased latency caused by a consistently high rate of lease transfers between datacenters in the following case:- Your cluster runs in datacenters which are very different distances away from each other.
- Each node was started with a single tier of
--locality, e.g.,--locality=datacenter=a. - Most client requests get sent to a single datacenter because that’s where all your application traffic is.
--locality=region=foo,datacenter=a and --locality=region=foo,datacenter=b, while restarting nodes in datacenter C with a different region, --locality=region=bar,datacenter=c.
Overload resolution for collated strings
Many string operations are not properly overloaded for , for example:Max size of a single column family
When creating or updating a row, if the combined size of all values in a single exceeds the for the table, the operation may fail, or cluster performance may suffer. As a workaround, you can either , or you can with an increased max range size.Simultaneous client connections and running queries on a single node
When a node has both a high number of client connections and running queries, the node may crash due to memory exhaustion. This is due to CockroachDB not accurately limiting the number of clients and queries based on the amount of available RAM on the node. To prevent memory exhaustion, monitor each node’s memory usage and ensure there is some margin between maximum CockroachDB memory usage and available system RAM. For more details about memory usage in CockroachDB, see this blog post. To control the maximum number of non-superuser ( user or other ) connections a can have open at one time, use theserver.max_connections_per_gateway . If a new non-superuser connection would exceed this limit, the error message "sorry, too many clients already" is returned, along with error code 53300. This may be useful in addition to your memory monitoring.
Privileges for DELETE and UPDATE
Every or statement constructs a SELECT statement, even when no WHERE clause is involved. As a result, the user executing DELETE or UPDATE requires both the DELETE and SELECT or UPDATE and SELECT on the table.
ROLLBACK TO SAVEPOINT in high-priority transactions containing DDL
Transactions with that contain DDL and ROLLBACK TO SAVEPOINT are not supported, as they could result in a deadlock. For example:
CockroachDB does not test for all connection failure scenarios
CockroachDB servers rely on the network to report when a TCP connection fails. In most scenarios when a connection fails, the network immediately reports a connection failure, resulting in aConnection refused error.
However, if there is no host at the target IP address, or if a firewall rule blocks traffic to the target address and port, a TCP handshake can linger while the client network stack waits for a TCP packet in response to network requests. To work around this kind of scenario, we recommend the following:
- When migrating a node to a new machine, keep the server listening at the previous IP address until the cluster has completed the migration.
- Configure any active network firewalls to allow node-to-node traffic.
- Verify that orchestration tools (e.g., Kubernetes) are configured to use the correct network connection information.
Some column-dropping schema changes do not roll back properly
Some that cannot be properly. In some cases, the rollback will succeed, but the column data might be partially or totally missing, or stale due to the asynchronous nature of the schema change. In other cases, the rollback will fail in such a way that will never be cleaned up properly, leaving the table descriptor in a state where no other schema changes can be run successfully. To reduce the chance that a column drop will roll back incorrectly:- Perform column drops in transactions separate from other schema changes. This ensures that other schema change failures will not cause the column drop to be rolled back.
- Drop all (including ) on the column in a separate transaction, before dropping the column.
- Drop any or on a column before attempting to drop the column. This prevents conflicts between constraints and default/computed values during a column drop rollback.
cannot be reverted, manual cleanup may be required might require manual intervention.
Remove a UNIQUE index created as part of CREATE TABLE
created as part of a statement cannot be removed without using . Unique indexes created with do not have this limitation.
Secondary regions and regional by row tables
are not compatible with databases containing tables. CockroachDB does not prevent you from defining secondary regions on databases with regional by row tables, but the interaction of these features is not supported. Therefore, Cockroach Labs recommends that you avoid defining secondary regions on databases that use regional by row table configurations.Row-Level TTL limitations
- Any queries you run against tables with Row-Level TTL enabled do not filter out expired rows from the result set (this includes and ). This feature may be added in a future release. For now, follow the instructions in .
- Enabling Row-Level TTL on a table with multiple can have negative performance impacts on a cluster, including increased and . This is particularly true for large tables with terabytes of data and billions of rows that are split up into multiple ranges across separate nodes.
- Increased latency may occur because secondary indexes aren’t necessarily stored on the same underlying as a table’s . Further, the secondary indexes’ ranges may have located on different nodes than the primary index.
- Increased contention may occur because must be written as part of performing the deletions.
- Finally, secondary indexes can also have a negative impact on the overall performance of . According to internal testing, the is worse on tables with secondary indexes. If you encounter this situation, decreasing the may help by decreasing the number of ranges that need to be accessed by the job.
Change data capture limitations
Change data capture (CDC) provides efficient, distributed, row-level changefeeds into Apache Kafka for downstream processing such as reporting, caching, or full-text indexing. It has the following known limitations:- Changefeed target options are limited to tables and .
- and in CockroachDB Advanced clusters do not support connecting to a sink’s internal IP addresses for . To connect to a Kafka sink from CockroachDB Advanced, it is necessary to expose the Kafka cluster’s external IP address and open ports with firewall rules to allow access from a CockroachDB Advanced cluster.
- Webhook sinks only support HTTPS. Use the parameter when testing to disable certificate verification; however, this still requires HTTPS and certificates.
- Formats for changefeed messages are not supported by all changefeed sinks. Refer to the page for details on compatible formats with each sink and the option to specify a changefeed message format.
- Using the and options on the same changefeed will cause an error when using the following : Kafka and Google Cloud Pub/Sub. Instead, use the individual
FAMILYkeyword to specify column families when creating a changefeed. - Changefeed types are not fully integrated with . Running changefeeds with user-defined composite types is in . Certain changefeed types do not support user-defined composite types. Refer to the change data capture for more detail. The following limitations apply:
- A changefeed in will not be able to serialize .
- A changefeed emitting will include
ASlabels in the message format when the changefeed serializes a .
- You can only apply CDC queries on a single table in each statement.
- Some , notably functions that return MVCC timestamps, are overridden to return the MVCC timestamp of the event, e.g.,
transaction_timestamporstatement_timestamp. Additionally, some , such asnow()are not supported. We recommend using thetransaction_timestamp()function or thecrdb_internal_mvcc_timestampcolumn instead. - The following are not permitted in CDC queries:
- .
- Sub-select queries.
- and (i.e., functions operating over many rows).
deletechangefeed events will only contain the . All other columns will emit asNULL. See for detail on running a CDC query that emits the deleted values.ALTER CHANGEFEEDis not fully supported with changefeeds that use CDC queries. . You can alter the options that a changefeed uses, but you cannot alter the changefeed target tables.- Creating a changefeed with CDC queries on tables with more than one column family is not supported.
- When you create a changefeed on a table with more than one column family , the changefeed will emit messages per column family in separate streams. As a result, for different column families will arrive at the under separate topics.

