Hanzo
Services

Hanzo DB

Serverless PostgreSQL with pgvector, auto-scaling, instant branching, connection pooling, and point-in-time recovery.

Hanzo DB

Hanzo DB is a serverless PostgreSQL service purpose-built for AI infrastructure. It provides auto-scaling compute, instant database branching for development workflows, pgvector for embedding storage, connection pooling, automatic backups, and point-in-time recovery -- all managed as part of the Hanzo platform.

Endpoint: db.hanzo.ai Gateway: api.hanzo.ai/v1/db/* In-cluster: postgres.hanzo.svc:5432 Version: PostgreSQL 16 with pgvector 0.7+

Features

  • Serverless PostgreSQL: Auto-scaling compute that scales to zero when idle and spins up on demand
  • pgvector: First-class vector embedding storage and similarity search for AI workloads
  • Connection Pooling: Built-in PgBouncer pooling with transaction and session modes
  • Instant Branching: Copy-on-write database branches for development, staging, and CI
  • Point-in-Time Recovery: Restore to any second within the retention window
  • Read Replicas: Horizontally scale read-heavy workloads across replica endpoints
  • Automatic Backups: Continuous WAL archiving with configurable retention (default 7 days)
  • SQL and REST APIs: Connect via standard PostgreSQL wire protocol or HTTP REST
  • OIDC Integration: Authenticate with hanzo.id for console and management API access
  • Role-Based Access: Fine-grained database and schema-level permissions

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│  Clients                                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌───────────────────┐   │
│  │  psql    │  │ Python   │  │ Node.js  │  │ Hanzo Services    │   │
│  │          │  │ asyncpg  │  │ pg       │  │ (IAM, Console...) │   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └─────────┬─────────┘   │
│       │              │              │                  │             │
└───────┼──────────────┼──────────────┼──────────────────┼─────────────┘
        │              │              │                  │
        ▼              ▼              ▼                  ▼
┌──────────────────────────────────────────────────────────────────────┐
│  db.hanzo.ai / postgres.hanzo.svc:5432                               │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  Connection Pooler (PgBouncer)                                 │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌────────────────────┐    │  │
│  │  │ Transaction  │  │  Session    │  │  Statement         │    │  │
│  │  │ Mode (6432)  │  │  Mode       │  │  Mode              │    │  │
│  │  └─────────────┘  └─────────────┘  └────────────────────┘    │  │
│  └──────────────────────────┬─────────────────────────────────────┘  │
│                             ▼                                        │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │  PostgreSQL 16                                                 │  │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌──────────────┐  │  │
│  │  │ pgvector  │ │ Branching │ │ WAL       │ │ Read         │  │  │
│  │  │ HNSW/IVF  │ │ (CoW)     │ │ Archiving │ │ Replicas     │  │  │
│  │  └───────────┘ └───────────┘ └───────────┘ └──────────────┘  │  │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌──────────────┐  │  │
│  │  │ PITR      │ │ Auto      │ │ pg_stat   │ │ Row-Level    │  │  │
│  │  │ Recovery  │ │ Vacuum    │ │ Monitoring │ │ Security     │  │  │
│  │  └───────────┘ └───────────┘ └───────────┘ └──────────────┘  │  │
│  └────────────────────────────────────────────────────────────────┘  │
│                             │                                        │
│                   ┌─────────┴──────────┐                            │
│                   │  Persistent Volume  │                            │
│                   │  (NVMe / Block)     │                            │
│                   └────────────────────┘                            │
└──────────────────────────────────────────────────────────────────────┘

Quick Start

Connect with psql

# Direct connection
psql "postgresql://user:[email protected]:5432/mydb?sslmode=require"

# In-cluster (from Hanzo K8s workloads)
psql "postgresql://user:[email protected]:5432/mydb"

# Via pooler (recommended for applications)
psql "postgresql://user:[email protected]:6432/mydb?sslmode=require"

Python (asyncpg)

import asyncio
import asyncpg

async def main():
    conn = await asyncpg.connect(
        host="db.hanzo.ai",
        port=5432,
        user="myuser",
        password="mypassword",
        database="mydb",
        ssl="require",
    )

    # Create a table
    await conn.execute("""
        CREATE TABLE IF NOT EXISTS documents (
            id    SERIAL PRIMARY KEY,
            title TEXT NOT NULL,
            body  TEXT,
            created_at TIMESTAMPTZ DEFAULT now()
        )
    """)

    # Insert
    await conn.execute(
        "INSERT INTO documents (title, body) VALUES ($1, $2)",
        "Getting Started", "Welcome to Hanzo DB.",
    )

    # Query
    rows = await conn.fetch("SELECT id, title, created_at FROM documents")
    for row in rows:
        print(f"{row['id']}: {row['title']} ({row['created_at']})")

    await conn.close()

asyncio.run(main())

Install:

pip install asyncpg

Node.js (pg)

import { Pool } from 'pg'

const pool = new Pool({
  host: 'db.hanzo.ai',
  port: 6432, // pooler
  user: 'myuser',
  password: 'mypassword',
  database: 'mydb',
  ssl: { rejectUnauthorized: true },
  max: 20,
})

// Create table
await pool.query(`
  CREATE TABLE IF NOT EXISTS documents (
    id         SERIAL PRIMARY KEY,
    title      TEXT NOT NULL,
    body       TEXT,
    created_at TIMESTAMPTZ DEFAULT now()
  )
`)

// Insert
await pool.query(
  'INSERT INTO documents (title, body) VALUES ($1, $2)',
  ['Getting Started', 'Welcome to Hanzo DB.']
)

// Query
const { rows } = await pool.query('SELECT id, title, created_at FROM documents')
for (const row of rows) {
  console.log(`${row.id}: ${row.title} (${row.created_at})`)
}

await pool.end()

Install:

npm install pg

REST API

Query your database over HTTP when a persistent connection is not practical:

# Execute a SQL query
curl -X POST https://api.hanzo.ai/v1/db/query \
  -H "Authorization: Bearer hk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "database": "mydb",
    "query": "SELECT id, title FROM documents LIMIT 10"
  }'

# List databases
curl -H "Authorization: Bearer hk-your-api-key" \
  https://api.hanzo.ai/v1/db/databases

# Get database info
curl -H "Authorization: Bearer hk-your-api-key" \
  https://api.hanzo.ai/v1/db/databases/mydb

pgvector -- Vector Embeddings

Hanzo DB includes pgvector for storing and querying vector embeddings directly alongside your relational data. No separate vector database required.

Enable the Extension

CREATE EXTENSION IF NOT EXISTS vector;

Create a Vector Table

CREATE TABLE embeddings (
    id        SERIAL PRIMARY KEY,
    content   TEXT NOT NULL,
    metadata  JSONB DEFAULT '{}',
    embedding vector(1536)  -- OpenAI text-embedding-3-small dimension
);

Insert Embeddings

import asyncpg
import httpx

async def store_embedding(conn, content: str, api_key: str):
    # Generate embedding via Hanzo LLM Gateway
    resp = httpx.post(
        "https://api.hanzo.ai/v1/embeddings",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"model": "text-embedding-3-small", "input": content},
    )
    vector = resp.json()["data"][0]["embedding"]

    await conn.execute(
        "INSERT INTO embeddings (content, embedding) VALUES ($1, $2)",
        content, str(vector),
    )
-- Nearest neighbors (cosine distance)
SELECT id, content, 1 - (embedding <=> $1::vector) AS similarity
FROM embeddings
ORDER BY embedding <=> $1::vector
LIMIT 10;

-- L2 distance
SELECT id, content, embedding <-> $1::vector AS distance
FROM embeddings
ORDER BY embedding <-> $1::vector
LIMIT 10;

-- Inner product (for normalized vectors)
SELECT id, content, (embedding <#> $1::vector) * -1 AS similarity
FROM embeddings
ORDER BY embedding <#> $1::vector
LIMIT 10;

Indexing

Create indexes for fast approximate nearest neighbor (ANN) queries:

-- HNSW index (recommended for most workloads)
CREATE INDEX ON embeddings
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

-- IVFFlat index (faster builds, good for large datasets)
CREATE INDEX ON embeddings
  USING ivfflat (embedding vector_cosine_ops)
  WITH (lists = 100);
Index TypeBuild SpeedQuery SpeedMemoryBest For
HNSWSlowerFastestHigherProduction queries, low latency
IVFFlatFasterFastLowerLarge datasets, batch workloads

Connection Pooling

All Hanzo DB endpoints include a built-in PgBouncer connection pooler to efficiently multiplex application connections to PostgreSQL backends.

Pooler Endpoint

# Pooled connection (recommended for applications)
postgresql://user:[email protected]:6432/mydb

# Direct connection (for migrations, LISTEN/NOTIFY, advisory locks)
postgresql://user:[email protected]:5432/mydb

Pool Modes

ModePortUse Case
Transaction6432Default. Connections returned after each transaction. Best for web apps and APIs.
Session5432Connection held for entire session. Required for prepared statements and LISTEN/NOTIFY.

Tuning

Set pool size based on your workload:

# Check active connections
psql -c "SELECT count(*) FROM pg_stat_activity WHERE state = 'active';"

# Check pooler stats
psql -p 6432 -c "SHOW POOLS;"

Recommended pool sizes per application:

Workloadmax connections
Web API10-20
Background worker3-5
Migration runner1
Analytics5-10

Branching

Database branches are copy-on-write clones that share storage with the parent until data diverges. Use them for development, staging, CI test runs, and schema previews.

Create a Branch

# Create a branch from the current state
curl -X POST https://api.hanzo.ai/v1/db/branches \
  -H "Authorization: Bearer hk-your-api-key" \
  -d '{"database": "mydb", "name": "feature-auth-refactor"}'

# Create a branch from a specific point in time
curl -X POST https://api.hanzo.ai/v1/db/branches \
  -H "Authorization: Bearer hk-your-api-key" \
  -d '{"database": "mydb", "name": "debug-2026-02-20", "restore_to": "2026-02-20T15:30:00Z"}'

Connect to a Branch

psql "postgresql://user:[email protected]:5432/mydb:feature-auth-refactor?sslmode=require"

List and Delete Branches

# List all branches
curl -H "Authorization: Bearer hk-your-api-key" \
  https://api.hanzo.ai/v1/db/branches?database=mydb

# Delete a branch
curl -X DELETE https://api.hanzo.ai/v1/db/branches/feature-auth-refactor \
  -H "Authorization: Bearer hk-your-api-key"

Branch Workflow

main (production)

  ├── feature-auth ─────── develop, test, merge

  ├── staging ──────────── pre-production validation

  └── ci-run-4821 ──────── ephemeral, auto-deleted after CI

Branches are near-instant to create regardless of database size because they use copy-on-write storage. They incur storage cost only for changed pages.

Backup and Recovery

Automatic Backups

Hanzo DB continuously archives WAL (Write-Ahead Log) segments. No cron jobs or manual snapshots required.

SettingDefaultDescription
Retention7 daysConfigurable up to 30 days
FrequencyContinuousWAL segments archived as they are produced
Granularity1 secondRestore to any point within the retention window

Point-in-Time Recovery

Restore a database to any second within the backup retention window:

# Restore to a specific timestamp
curl -X POST https://api.hanzo.ai/v1/db/restore \
  -H "Authorization: Bearer hk-your-api-key" \
  -d '{
    "database": "mydb",
    "restore_to": "2026-02-20T14:30:00Z",
    "target": "mydb-restored"
  }'

The restored database appears as a new database. Verify its state before swapping with production.

Manual Snapshots

Take an on-demand snapshot for pre-migration safety:

curl -X POST https://api.hanzo.ai/v1/db/snapshots \
  -H "Authorization: Bearer hk-your-api-key" \
  -d '{"database": "mydb", "label": "pre-migration-v42"}'

Read Replicas

Scale read-heavy workloads by routing queries to read replicas:

# Create a read replica
curl -X POST https://api.hanzo.ai/v1/db/replicas \
  -H "Authorization: Bearer hk-your-api-key" \
  -d '{"database": "mydb", "name": "mydb-ro-1"}'

Connect applications to the read replica endpoint:

# Read replica (eventually consistent)
postgresql://user:[email protected]:5432/mydb-ro-1?sslmode=require

Typical replication lag is under 100ms for in-cluster replicas.

Platform Databases

The Hanzo platform uses the following databases on postgres.hanzo.svc:

DatabaseServicePurpose
iamHanzo IAM (hanzo.id)Users, organizations, applications, OAuth providers
cloudHanzo CloudCloud backend state, AI provider configs, usage records
consoleHanzo ConsoleProjects, API keys, prompts, evaluation datasets
hanzo_cloudHanzo Cloud (legacy)Legacy cloud data, billing records
kmsHanzo KMSSecrets, machine identities, audit logs
platformHanzo PlatformPaaS deployment state, build configs, domains
commerceHanzo CommerceProducts, orders, customers, payments

These databases are managed by the platform and should not be modified directly. Use the respective service APIs to interact with them.

Monitoring

Built-in Metrics

Hanzo DB exports PostgreSQL metrics to Hanzo Analytics and Prometheus:

-- Active connections
SELECT count(*) FROM pg_stat_activity;

-- Database sizes
SELECT datname, pg_size_pretty(pg_database_size(datname))
FROM pg_database WHERE datistemplate = false;

-- Slow queries (>1s)
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 20;

-- Table bloat
SELECT schemaname, tablename, n_dead_tup, n_live_tup,
       round(n_dead_tup::numeric / greatest(n_live_tup, 1) * 100, 2) AS dead_pct
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

Extensions

The following extensions are available and can be enabled per-database:

ExtensionPurpose
vectorpgvector -- vector similarity search
pg_stat_statementsQuery performance statistics
pg_trgmTrigram text similarity and fuzzy search
btree_ginGIN index support for scalar types
uuid-osspUUID generation functions
hstoreKey-value pairs within a single column
citextCase-insensitive text type
postgisGeographic objects and spatial queries

Enable any extension:

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

How is this guide?

Last updated on

On this page