You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document tracks PostgreSQL feature compatibility for the Turso Postgres
frontend. The feature list is based on the official
PostgreSQL feature matrix,
with additional rows for baseline features the matrix does not enumerate.
Status legend:
Status
Meaning
✅ Supported
Feature works and is covered by tests
🟡 Partial
Feature works with limitations (see notes)
❌ Not supported
Feature is not implemented
Architecture
The frontend parses SQL with pg_query (libpg_query, the real PostgreSQL
grammar), so virtually all PostgreSQL syntax is accepted at parse time.
Support is decided by the translator (postgres/parser/translator.rs), which
converts the PostgreSQL AST into Turso's native AST, and by what the Turso
engine can execute. Components:
postgres/parser — parse + translate PostgreSQL SQL to Turso AST
postgres/server — PostgreSQL wire protocol (v3) server, built on pgwire
postgres/cli — tursopg, a psql-like REPL that can also host the server
Because the parser accepts the full PostgreSQL grammar, some clauses parse
and run but their semantics are silently dropped, producing wrong results or
lost information without any error. These are called out as "silently
ignored" in the notes of the tables below.
Core SQL baseline
Basics not enumerated by the official feature matrix.
Feature
Status
Notes
SELECT (projections, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT/OFFSET)
= ANY(array) and <> ALL(array) work, including bound text-array parameters; other ANY/ALL array operators are rejected; ALL/row comparison subqueries error
PK, NOT NULL, UNIQUE, DEFAULT, CHECK, FK (with ON DELETE/UPDATE actions); IF NOT EXISTS; tables are created STRICT
CREATE TABLE AS / SELECT INTO
✅ Supported
Schema derived from the SELECT; WITH NO DATA supported (lowered to LIMIT 0, so errors in an overridden LIMIT go unreported); explicit column list rejected; INTO on the first leaf of a compound SELECT (legal in PG) rejected; TEMP silently ignored; completes with SELECT n like PostgreSQL, though an IF NOT EXISTS skip tags SELECT 0 instead of CREATE TABLE AS
ALTER TABLE
🟡 Partial
ADD/DROP COLUMN, RENAME TABLE/COLUMN work; ALTER COLUMN TYPE translates but fails at execution; SET/DROP DEFAULT, SET/DROP NOT NULL, ADD CONSTRAINT rejected
CREATE INDEX
✅ Supported
UNIQUE, multi-column, partial (WHERE), expression indexes, IF NOT EXISTS
CREATE VIEW
✅ Supported
Column aliases supported; TEMP silently ignored
COMMENT ON
🟡 Partial
Accepted but discarded; comments are not persisted in pg_description
CREATE SCHEMA / DROP SCHEMA
✅ Supported
Schemas are ATTACHed databases; DROP ... CASCADE; public is special-cased
In FROM and with joins; column aliases on the function (AS g(x)) do not resolve
pg_catalog emulation
🟡 Partial
See Backend section
SET / SHOW
🟡 Partial
Passed through as PRAGMAs; no PostgreSQL GUCs (e.g. SHOW search_path returns nothing)
Backend
The pg_catalog tables emulated (live, reflecting real schema): pg_class,
pg_namespace, pg_attribute, pg_type (builtin + array + enum types),
pg_index, pg_constraint, pg_attrdef, pg_tables, pg_sequences,
pg_database, pg_roles (single hardcoded turso role), pg_proc, pg_am,
plus pg_input_error_info. Present but always empty: pg_policy,
pg_trigger, pg_statistic_ext, pg_inherits, pg_rewrite,
pg_foreign_table, pg_partitioned_table, pg_collation, pg_description,
pg_publication*. Catalog introspection functions: format_type,
pg_get_constraintdef, pg_get_indexdef, pg_get_expr (returns TursoPG's
stored SQL; relation oid and pretty printing do not change the output),
pg_get_userbyid, pg_*_is_visible, pg_encoding_to_char,
pg_input_is_valid, to_char (numeric), now/clock_timestamp/
transaction_timestamp/statement_timestamp.
Session information functions: version(), current_database() /
current_catalog, current_schema (call, bare-keyword, and FROM-position
forms), pg_backend_pid(), quote_ident(), quote_literal();
obj_description()/col_description() always return NULL because COMMENT ON
is not persisted. DML against pg_catalog is rejected. pg_typeof is not
implemented.
Feature
Status
Notes
64-bit large objects
❌ Not supported
Advisory locks
❌ Not supported
Custom background workers
❌ Not supported
Disk based FSM
❌ Not supported
Dynamic Background Workers
❌ Not supported
EXPLAIN (BUFFERS) support
❌ Not supported
EXPLAIN is not supported at all
EXPLAIN (MEMORY)
❌ Not supported
EXPLAIN (SERIALIZE) support
❌ Not supported
EXPLAIN (WAL) support
❌ Not supported
"jsonlog" logging format
❌ Not supported
Loadable plugin infrastructure for monitoring the planner
❌ Not supported
Payload support for LISTEN/NOTIFY
❌ Not supported
LISTEN/NOTIFY not supported
pg_stat_checkpointer system view
❌ Not supported
pg_stat_io - I/O metrics view
❌ Not supported
pg_wait_events system view
❌ Not supported
Server statistics in shared memory
❌ Not supported
SQL-standard information schema
❌ Not supported
Only an information_schema row in pg_namespace; no views
Support for anonymous shared memory
❌ Not supported
XML, JSON and YAML output for EXPLAIN
❌ Not supported
Data Types, Functions, & Operators
Type mapping: serial/smallserial/bigserial (and serial2/4/8) become
INTEGER NOT NULL DEFAULT nextval(...) with an implicit sequence. boolean,
smallint, bigint, uuid, date, time, timestamp[tz], bytea, json, jsonb, inet,
cidr, macaddr, macaddr8 map to Turso custom types. varchar(n)/char(n) and
numeric(p,s) keep their type modifiers. interval, xml, tsvector/tsquery,
bit/varbit, geometric types degrade to TEXT; money to REAL; OID/reg* types to
INTEGER. Unknown type names pass through as custom types.
CREATE TYPE ... AS ENUM; values validated on write; DROP TYPE [IF EXISTS]
GUID/UUID data type
✅ Supported
uuid columns, gen_random_uuid(), input validation, text casts
macaddr8 data type
✅ Supported
Along with inet, cidr, macaddr (round-trip tested)
Multiranges
❌ Not supported
NULLs in Array
✅ Supported
ARRAY[1, NULL, 3] round-trips
Phrase search
❌ Not supported
tsvector/tsquery degrade to TEXT; no full-text search
Range types
❌ Not supported
smallserial type
✅ Supported
serial2/serial4/serial8 aliases too; serial implies NOT NULL + implicit sequence, not PRIMARY KEY
Type modifier support
✅ Supported
varchar(n) length enforced ("value too long for varchar"); numeric(p,s) scale applied
UUIDv7
❌ Not supported
XML data type
❌ Not supported
xml columns degrade to TEXT; no XML functions
Indexing & Constraints
Feature
Status
Notes
Block-range (BRIN) indexes
❌ Not supported
B-tree bottom-up index deletion
❌ Not supported
B-tree deduplication
❌ Not supported
Concurrent GiST indexes
❌ Not supported
Covering Indexes for B-trees (INCLUDE)
❌ Not supported
INCLUDE clause silently ignored
Covering indexes for GiST (INCLUDE)
❌ Not supported
Deferrable unique constraints
❌ Not supported
Exclusion constraints
❌ Not supported
GIN (Generalized Inverted Index) indexes
❌ Not supported
USING <method> silently ignored; every index is a B-tree
GIN indexes partial match
❌ Not supported
GIN index performance and size improvements
❌ Not supported
GiST (Generalized Search Tree) indexes
❌ Not supported
Indexes on expressions
✅ Supported
Partial (WHERE) indexes also supported
Index-only scans
❌ Not supported
Index-only scans on GiST
❌ Not supported
Index support for IS NULL
❌ Not supported
In-memory Bitmap Indexes
❌ Not supported
K-nearest neighbor GiST support
❌ Not supported
K-nearest neighbor SP-GiST support
❌ Not supported
Non-blocking CREATE INDEX
❌ Not supported
CONCURRENTLY silently ignored
Parallel B-tree index scans
❌ Not supported
Parallelized CREATE INDEX for BRIN indexes
❌ Not supported
Parallelized CREATE INDEX for B-tree indexes
❌ Not supported
Parallelized CREATE INDEX for GIN indexes
❌ Not supported
Skip scan on multicolumn B-tree indexes
❌ Not supported
Space-Partitioned GiST (SP-GiST) indexes
❌ Not supported
SP-GiST indexes for range types
❌ Not supported
UNIQUE NULLS NOT DISTINCT
❌ Not supported
Silently ignored
WAL support for hash indexes
❌ Not supported
SQL
Feature
Status
Notes
ANY_VALUE aggregate
❌ Not supported
DISTINCT ON
❌ Not supported
Accepted but silently degrades to plain DISTINCT (wrong results)
FETCH FIRST .. WITH TIES
❌ Not supported
FETCH FIRST n ROWS ONLY works (lowered to LIMIT); WITH TIES silently ignored
GROUPING SETS, CUBE and ROLLUP support
❌ Not supported
Translation error
INSERT/UPDATE/DELETE RETURNING
✅ Supported
Including RETURNING * and UPDATE ... FROM ... RETURNING
LATERAL clause
❌ Not supported
Keyword accepted but silently ignored
MERGE
❌ Not supported
MERGE ... RETURNING
❌ Not supported
Multirow VALUES
✅ Supported
In INSERT and as standalone VALUES lists
ORDER BY / LIMIT on a standalone VALUES list
❌ Not supported
Rejected: "ORDER BY clause is not allowed with VALUES clause"
Non-decimal integer literals
✅ Supported
0x, 0o, 0b
ORDER BY NULLS FIRST/LAST
✅ Supported
Honored in SELECT, window, and compound SELECT ORDER BY; rejected (matching SQLite) in CREATE INDEX
range_agg range type aggregation function
❌ Not supported
Recursive queries
🟡 Partial
WITH RECURSIVE works with SQLite semantics (row-at-a-time recursive term, so e.g. DISTINCT in the recursive term over a multi-row anchor can differ from PG); SEARCH/CYCLE clauses are rejected
regexp_count, regexp_instr, regexp_like
❌ Not supported
Regex operators (~, ~*, SIMILAR TO) work
Return OLD and NEW values from modified rows
❌ Not supported
Row-wise comparison
❌ Not supported
Row constructors (a,b) < (c,d) fail to translate
SELECT ... FOR UPDATE/SHARE
❌ Not supported
Accepted but silently ignored — no locking happens
SELECT FOR NO KEY UPDATE/SELECT FOR KEY SHARE lock modes
❌ Not supported
Accepted but silently ignored — no locking happens
SQL standard interval handling
❌ Not supported
interval degrades to TEXT; no interval arithmetic
SYSTEM_USER
❌ Not supported
current_user/current_role return stub values
TABLE statement
✅ Supported
Underscores (_) for thousands separators
✅ Supported
unnest/array_agg
🟡 Partial
array_agg works; unnest is not implemented
Upsert (INSERT ... ON CONFLICT DO ...)
✅ Supported
DO NOTHING and DO UPDATE SET ... (with EXCLUDED and conflict targets)
Window functions
🟡 Partial
Aggregate window functions (COUNT/SUM/AVG/MIN/MAX OVER), row_number, PARTITION BY/ORDER BY, frame clauses, and named WINDOW clauses work; rank, dense_rank, lag, lead, etc. are not implemented
SQL-level PREPARE/EXECUTE/DEALLOCATE are not translated
Version aware psql
❌ Not supported
Additional Modules (contrib)
Feature
Status
Notes
adminpack
❌ Not supported
auth_delay
❌ Not supported
auto_explain
❌ Not supported
btree_gin
❌ Not supported
btree_gist
❌ Not supported
citext
❌ Not supported
dblink
❌ Not supported
dblink asynchronous notification support
❌ Not supported
file_fdw
❌ Not supported
fuzzystrmatch
❌ Not supported
hstore
❌ Not supported
intarray
❌ Not supported
isn (ISBN)
❌ Not supported
KNN support for CUBE
❌ Not supported
ltree
❌ Not supported
pageinspect
❌ Not supported
passwordcheck
❌ Not supported
pg_buffercache
❌ Not supported
pg_freespacemap
❌ Not supported
pg_logicalinspect
❌ Not supported
pg_overexplain
❌ Not supported
pg_stat_statements
❌ Not supported
pgstattuple
❌ Not supported
pg_trgm
❌ Not supported
pg_trgm regular expressions indexing
❌ Not supported
pg_walinspect
❌ Not supported
seg
❌ Not supported
sepgsql
❌ Not supported
sslinfo
❌ Not supported
tablefunc
❌ Not supported
tcn
❌ Not supported
tsearch2 compatibility wrapper
❌ Not supported
unaccent
❌ Not supported
uuid-ossp
❌ Not supported
gen_random_uuid() (core) is available
xml2
❌ Not supported
Network
Feature
Status
Notes
Full SSL support
❌ Not supported
SSLRequest answered with "SSL not available"; plaintext only
IPv6 support
🟡 Partial
Server binds whatever address it is given, including IPv6 literals; no dual-stack handling
V2 client protocol
❌ Not supported
V3 client protocol
🟡 Partial
Via pgwire: simple query and extended query (Parse/Bind/Execute/Describe/Sync) protocols; trust auth only; parameter values must be text-format; Execute row limits ignored (no portal suspension); no COPY sub-protocol, CancelRequest, or NotificationResponse
Platforms
Not applicable: the Turso Postgres frontend is Rust and builds on every
platform Turso supports; PostgreSQL's platform/compiler feature entries do
not carry over.