Skip to content

PostgreSQL Wire Protocol

Zatabase implements the PostgreSQL wire protocol (v3.0), allowing you to connect using any standard PostgreSQL client or driver. This means existing tools, ORMs, and database GUIs that support PostgreSQL can work with Zatabase with zero code changes.

Connect to Zatabase using your project endpoint. The SDK handles routing automatically — no port configuration needed.

Terminal window
# Connect with psql
psql "postgresql://admin@example.com:password@your-project.zatabase.io/zatabase"
ParameterDefaultDescription
Hostyour-project.zatabase.ioYour project endpoint
User(required)Your Zatabase username (email)
DatabasezatabaseDatabase name (maps to Zatabase organization)

Zatabase supports SCRAM-SHA-256 authentication over the wire protocol, the same mechanism used by modern PostgreSQL servers. This provides secure password exchange without transmitting the password in cleartext.

Terminal window
# psql will prompt for password
psql "host=your-project.zatabase.io user=admin@example.com dbname=zatabase sslmode=require"

Standard PostgreSQL connection string syntax is supported:

postgresql://admin@example.com:password@your-project.zatabase.io/zatabase

Or the key-value format:

host=your-project.zatabase.io user=admin@example.com password=SecurePass123! dbname=zatabase

The wire protocol supports the same SQL subset as the HTTP API. See the SQL Reference for complete syntax:

-- DDL
CREATE TABLE products (name TEXT, price FLOAT, quantity INTEGER);
DROP TABLE products;
-- DML
INSERT INTO products (name, price, quantity) VALUES ('Widget', 9.99, 100);
SELECT * FROM products WHERE price > 5.0 ORDER BY name LIMIT 10;
DELETE FROM products WHERE name = 'Widget';
-- Vector operations
CREATE TABLE docs (title TEXT, embedding VECTOR(384));
SELECT * FROM docs ORDER BY embedding <-> ARRAY[0.1, 0.2, ...] LIMIT 5;

Zatabase’s wire protocol has been tested with the following PostgreSQL client libraries:

Terminal window
psql "postgresql://admin@example.com:password@your-project.zatabase.io/zatabase"
zatabase=# CREATE TABLE test (id INTEGER, name TEXT);
CREATE TABLE
zatabase=# INSERT INTO test (id, name) VALUES (1, 'Alice');
INSERT 0 1
zatabase=# SELECT * FROM test;
id | name
----+-------
1 | Alice
(1 row)
use tokio_postgres::NoTls;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (client, connection) = tokio_postgres::connect(
"host=your-project.zatabase.io user=admin@example.com password=pass dbname=zatabase",
NoTls,
).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
// Create table
client.execute(
"CREATE TABLE users (name TEXT, age INTEGER)",
&[],
).await?;
// Insert
client.execute(
"INSERT INTO users (name, age) VALUES ($1, $2)",
&[&"Alice", &30_i32],
).await?;
// Query
let rows = client.query(
"SELECT name, age FROM users WHERE name = $1",
&[&"Alice"],
).await?;
for row in &rows {
let name: &str = row.get(0);
let age: i32 = row.get(1);
println!("{}: {}", name, age);
}
Ok(())
}
use sqlx::postgres::PgPoolOptions;
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgresql://admin@example.com:pass@your-project.zatabase.io/zatabase")
.await?;
sqlx::query("CREATE TABLE items (name TEXT, price FLOAT)")
.execute(&pool)
.await?;
sqlx::query("INSERT INTO items (name, price) VALUES ($1, $2)")
.bind("Widget")
.bind(9.99_f64)
.execute(&pool)
.await?;
let rows = sqlx::query_as::<_, (String, f64)>(
"SELECT name, price FROM items WHERE price > $1"
)
.bind(5.0_f64)
.fetch_all(&pool)
.await?;
for (name, price) in rows {
println!("{}: ${:.2}", name, price);
}
Ok(())
}
import psycopg2
conn = psycopg2.connect(
host="your-project.zatabase.io",
user="admin@example.com",
password="SecurePass123!",
dbname="zatabase"
)
cur = conn.cursor()
cur.execute("CREATE TABLE sensors (location TEXT, temperature FLOAT)")
cur.execute("INSERT INTO sensors VALUES ('lab-1', 22.5)")
conn.commit()
cur.execute("SELECT * FROM sensors")
for row in cur.fetchall():
print(row)
conn.close()

Server-side wire protocol settings via environment variables:

VariableDefaultDescription
ZPG_BIND_PORT5432Port for PG wire protocol
ZPG_SSL_PORT5434Port for TLS connections
ZPG_MAX_CONNECTIONS100Maximum concurrent connections
ZPG_CONNECTION_TIMEOUT30Connection timeout in seconds
ZPG_AUTH_TIMEOUT30Authentication timeout in seconds
ZPG_MAX_AUTH_ATTEMPTS3Failed auth attempts before lockout
ZPG_LOCKOUT_DURATION900Lockout duration in seconds (15 min)
ZPG_TCP_NO_DELAYtrueDisable Nagle’s algorithm
ZPG_KEEP_ALIVEtrueEnable TCP keepalive

Enable encrypted connections by configuring the SSL port and providing certificate files:

Terminal window
export ZPG_SSL_ENABLED=true
export ZPG_SSL_CERT_PATH=/path/to/server.crt
export ZPG_SSL_KEY_PATH=/path/to/server.key

Clients can then connect with sslmode=require:

Terminal window
psql "host=your-project.zatabase.io user=admin@example.com dbname=zatabase sslmode=require"
  • Prepared statements: Basic support; complex parameterized queries may require the HTTP API
  • COPY protocol: Not currently supported; use the HTTP ingest endpoint for bulk loads
  • Cursors: Not supported; use LIMIT/OFFSET for pagination
  • System catalogs: pg_catalog queries return limited metadata
  • Extensions: PostgreSQL extensions (PostGIS, pgvector, etc.) are not available; Zatabase has its own native vector support