Skip to Content
We are live but in Staging 🎉
Data EnginesSQLLimits & differences

Limits & differences

Types

DifferenceStatusWhat to do
NUMERIC precision is capped at 38 digits; NUMERIC(p>38) is refused, never narrowed. Bare NUMERIC becomes (38,9) with a NOTICE.Refused42601Always declare NUMERIC(p,s) with p ≤ 38.
INTEGER / INT are stored as 64-bit and introspect as BIGINT.SupportedDeclare BIGINT if you want the catalog to match.
A function call inside VALUES (repeat(), upper(), …) is refused. Literals, typed literals, CURRENT_TIMESTAMP / now() and the default-expression functions are fine.Refused42601Compute in the application, or INSERT … SELECT expr. Backlog 0.1.44.
TIMESTAMP WITHOUT TIME ZONE is stored as timestamptz (UTC microseconds).Accepted · NOTICETreat every timestamp as UTC. Convert at the edge.
SET TimeZone changes nothing; the session is always UTC.Accepted · NOTICERender in the application. A render-only session time zone is under consideration.
No SERIAL sequences: SERIAL/BIGSERIAL/IDENTITY produce 64-bit generated ids, not a counter. No nextval / currval.SupportedRead generated ids back with RETURNING.
T[] and VECTOR(N) are advertised as text on the wire ({…} / […] literals), not a native array OID.PartialParse the literal client-side; bound array parameters work (= ANY($1)).
VECTOR without a dimension is refused.Refused42601VECTOR(768).
CHAR(n) is length-checked, not blank-padded.Supported since 0.1.43Pad in the application if fixed width matters.

Statements

Refused or differentStatusWhat to do
UPDATE / DELETE without WHERERefused42601WHERE TRUE to touch every row; TRUNCATE TABLE t to clear a table.
ALTER TABLE … RENAME COLUMN / RENAME TORefused0A000 since 0.1.44Copy with CREATE TABLE … AS SELECT, then DROP.
ALTER COLUMN other than SET DATA TYPE; narrowing retypesRefused42703Recreate the table.
DROP INDEXRefused42601DROP TABLE __idx_<table>_<col> / __uidx_….
Non-unique index on more than one column; index on an expressionRefused42601One index per column, or a UNIQUE index; materialise the expression.
DROP TABLE a, b, TRUNCATE a, b, TRUNCATE … PARTITION (…)Refused42601One table per statement.
CREATE VIEW, CREATE MATERIALIZED VIEW, CREATE SEQUENCERefused0A000 since 0.1.44A teaching refusal names the alternative (CREATE RULE stays 42601). CREATE TABLE … AS SELECT and refresh it; ids come from SERIAL or GENERATE_SNOWFLAKE_ID().
LOCK TABLE, pg_advisory_lock() and friendsRefused42601Nothing to lock. Guard a row with SELECT … FOR UPDATE instead (pg_advisory_lock() fails as an unknown relation, 42P01).
CREATE TRIGGER, CREATE EVENT TRIGGER, CREATE FUNCTION … RETURNS triggerRefused0A000 since 0.1.43Validation → CHECK; reactions → an ingest rule + pipeline, or an Action. A plpgsql-subset trigger engine is on the roadmap (0.1.44 backlog).
CHECK with a subquery, arithmetic or a function callRefused0A000Comparisons of a column with a literal or column, AND/OR/NOT, IS [NOT] NULL, [NOT] IN (literals), [NOT] BETWEEN, typed DATE/TIMESTAMP literals.
ON CONFLICT ON CONSTRAINT nameRefused42601Name the columns: ON CONFLICT (a, b).
MERGE with no equality on a same-named column in ON and no primary key; USING other than a table, VALUES or SELECT; non-literal VALUESRefused42601Add t.col = s.col; wrap the source in a SELECT.
COPY … TO, COPY … FROM '<file>'Refused42601COPY … FROM STDIN only; export with SELECT or the HTTP API.
Schemas: a non-public qualifier is not resolved.Refused42P01The bucket is the only namespace. public. is stripped; CREATE SCHEMA public and SET search_path are no-ops.
pg_catalog queries beyond the emulated set; information_schema.table_constraintsRefused42P01Use information_schema.tables / .columns, DESCRIBE, SHOW TABLES. See Catalog.

Transactions and concurrency

DifferenceStatusWhat to do
SELECT … FOR UPDATE takes no lock and never blocks; it guards the rows read and fails COMMIT with 40001 on conflict.SupportedWrap the write in a retry-on-40001 loop. See Transactions.
FOREIGN KEY is enforced on the insert side only (23503 on INSERT/UPSERT). Deleting a parent that has children succeeds; an autocommit UPDATE of an FK column, MERGE, and the gRPC WriteStream lane are not checked. Adding a constraint is not retroactive.PartialOwn the delete side in the application: delete children first, or guard the parent with FOR UPDATE and check.
ON DELETE / ON UPDATE CASCADE / SET NULL / SET DEFAULT, DEFERRABLE, INITIALLY DEFERRED on a foreign key.Refused0A000Drop the option. Cascades are the application’s job.
The catalog does not list foreign keys back to ORMs.PartialSuppress FK diffs in migration autogenerate.
SET TRANSACTION ISOLATION LEVEL changes nothing.Accepted · no effectThe model is fixed: snapshot reads + commit guard.
ON CONFLICT DO NOTHING inside an explicit transaction may report rowcount 1 for a row skipped at COMMIT.Partial since 0.1.43Read the row after COMMIT if the count matters. Backlog 0.1.44.
Interactive BEGIN over the HTTP/gRPC Execute API.RefusedSend BEGIN; …; COMMIT; in one call (DML only), or use the Postgres wire.
SELECT or DDL inside an Execute transaction block.RefusedIssue them outside the block. The Postgres wire has no such limit.
A semicolon-separated batch over Execute (without BEGIN/COMMIT).RefusedExecute takes one statement per call: split the batch and issue the statements in order. The Postgres wire accepts multi-statement simple queries.
A strong read may be refused under a heavy write backlog rather than served partially.PartialRetry shortly; run compact after bulk loads. See Errors.

Schema

DifferenceStatusWhat to do
RESTORE TABLE discards every later write, and does not roll indexes back.SupportedRebuild indexes after a restore.
Version history retention floor is 168 h; vacuum cannot go below it.SupportedPlan restores within the window.
CREATE TABLE … AS SELECT infers types (long, double, string, boolean); no primary key is declared.SupportedCreate the table with explicit columns first, then INSERT … SELECT.
A table without a PRIMARY KEY has a hidden _rowid key, visible in DESCRIBE, hidden from Postgres metadata.SupportedDeclare a primary key for OLTP tables.
TIMESTAMP(p) rounding is applied on SQL INSERT/UPDATE only — not on COPY FROM STDIN or the gRPC Upsert / WriteStream lanes (widths ARE enforced on every lane since 0.1.44).PartialRound timestamps before a bulk load. Backlog 0.1.45.
Reserved words at, end, order, table, to, user, offset as bare identifiers.Refused42601Quote them, or rename.

Wire and session

DifferenceStatusWhat to do
Server-side cursors are forward-only; SCROLL / FETCH BACKWARD are refused.PartialRe-declare the cursor.
COPY … FROM STDIN WITH (FORMAT csv) does not accept embedded newlines inside quoted fields.PartialUse the text format, or strip newlines.
LISTEN / NOTIFY, DEALLOCATE, DISCARD, RESET of unknown GUCs.Accepted · no effectAccepted, no effect.
GUCs honoured: statement_timeout, hnsw.ef_search, ivfflat.probes, dodil.vector_exact_scan, dodil.vector_consistency. Every other SET is a no-op.Partial—
A prepared read is executed once at Describe to learn its result schema.SupportedDrivers that prepare aggressively issue more reads than statements.
Extended-protocol Describe on a RETURNING DML answers with a zero-row probe.Supported—

Ingest lanes

DifferenceStatusWhat to do
Pipeline-bound tables materialise their schema on first ingest, not at creation.SupportedDESCRIBE after the first document lands.

Items that were on this page and are now fixed are documented where they belong, marked with the release that changed them: exact NUMERIC division and 22012 (0.1.43), VARCHAR(n) / TIMESTAMP(p) enforcement (0.1.43), ON CONFLICT DO NOTHING first-wins (0.1.43), FOR UPDATE through a JOIN (0.1.43), online ADD COLUMN (0.1.42), read-your-writes inside a prepared-statement transaction (0.1.42), indexes on populated tables (0.1.41), concurrent duplicate INSERT → 23505 (0.1.41), cross-table transactions and read-your-writes inside a transaction (2026-07).