Hanzo
Hanzo Skills Reference

Hanzo Database - PostgreSQL, Redis & Vector Storage

Hanzo Database covers the PostgreSQL (with pgvector), Redis/Valkey, MongoDB, and Hanzo S3 configurations used across the Hanzo ecosystem — all running in-cluster on K8s, no managed database services.

Overview

Hanzo Database covers the PostgreSQL (with pgvector), Redis, MongoDB, and Hanzo S3 configurations used across the Hanzo ecosystem. All databases run in-cluster on K8s — no managed database services (DO Managed DB decommissioned Feb 2026).

Why In-Cluster?

  • Cost: 5-10x cheaper than managed DBs at scale
  • Latency: Same-cluster networking, no external hops
  • Control: Full PostgreSQL config, extensions, versions
  • Consistency: Same setup across all environments

When to use

  • Configuring PostgreSQL for Hanzo services
  • Setting up pgvector for AI embeddings
  • Redis caching, sessions, and job queues
  • MongoDB for document storage (Chat)
  • Database troubleshooting and maintenance

Quick reference

DatabasePortImageUse Case
PostgreSQL5432postgres:16Primary RDBMS, pgvector
Redis6379redis:7-alpineCache, sessions, BullMQ queues
MongoDB27017mongo:7Document storage (Chat)
Hanzo S39000ghcr.io/hanzoai/s3S3-compatible object storage

Production Layout

hanzo-k8s Cluster

ServiceDatabaseHost
postgres.hanzo.svcShared PostgreSQL instance
iamHanzo IAM (hanzo.id)
cloudCloud dashboard
consoleObservability
hanzo_cloudCloud API
kmsKMS/Hanzo KMS
platformPaaS platform

lux-k8s Cluster

ServiceDatabaseHost
postgres.hanzo.svcShared PostgreSQL instance
cloudLux Cloud
commerceCommerce API
consoleConsole
gatewayAPI Gateway
hanzoCore Hanzo
kmsKMS

PostgreSQL + pgvector

Setup

-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Create embeddings table
CREATE TABLE embeddings (
    id SERIAL PRIMARY KEY,
    content TEXT NOT NULL,
    embedding vector(1536),       -- OpenAI ada-002 dimensions
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- IVFFlat index (fast approximate search)
CREATE INDEX ON embeddings
    USING ivfflat (embedding vector_cosine_ops)
    WITH (lists = 100);

-- HNSW index (better recall, more memory)
CREATE INDEX ON embeddings
    USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 64);
-- Cosine similarity (most common for embeddings)
SELECT content, 1 - (embedding <=> $1::vector) AS similarity
FROM embeddings
ORDER BY embedding <=> $1::vector
LIMIT 5;

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

-- Inner product
SELECT content, embedding <#> $1::vector AS score
FROM embeddings
ORDER BY embedding <#> $1::vector
LIMIT 5;

-- With metadata filter
SELECT content, 1 - (embedding <=> $1::vector) AS similarity
FROM embeddings
WHERE metadata->>'source' = 'docs'
ORDER BY embedding <=> $1::vector
LIMIT 5;

Python pgvector Usage

import psycopg2
from pgvector.psycopg2 import register_vector
import numpy as np

conn = psycopg2.connect(os.environ["DATABASE_URL"])
register_vector(conn)
cur = conn.cursor()

# Insert embedding
embedding = np.random.rand(1536).astype(np.float32)  # Your actual embedding
cur.execute(
    "INSERT INTO embeddings (content, embedding, metadata) VALUES (%s, %s, %s)",
    ("Hello world", embedding, '{"source": "docs"}')
)

# Similarity search
query_vec = np.random.rand(1536).astype(np.float32)  # Your query embedding
cur.execute(
    "SELECT content, 1 - (embedding <=> %s) AS similarity "
    "FROM embeddings ORDER BY embedding <=> %s LIMIT 5",
    (query_vec, query_vec)
)
for row in cur.fetchall():
    print(f"{row[0]}: {row[1]:.3f}")

conn.commit()

Go pgvector Usage

import (
    "github.com/jackc/pgx/v5"
    "github.com/pgvector/pgvector-go"
)

conn, _ := pgx.Connect(ctx, os.Getenv("DATABASE_URL"))

// Insert
embedding := pgvector.NewVector(floats)
conn.Exec(ctx,
    "INSERT INTO embeddings (content, embedding) VALUES ($1, $2)",
    "Hello world", embedding,
)

// Search
rows, _ := conn.Query(ctx,
    "SELECT content, 1 - (embedding <=> $1) AS similarity "+
    "FROM embeddings ORDER BY embedding <=> $1 LIMIT 5",
    pgvector.NewVector(queryVec),
)

Redis Patterns

# Connection
REDIS_URL=redis://redis.hanzo.svc:6379

# From K8s pod
redis-cli -h redis.hanzo.svc

Common Patterns

import redis

r = redis.from_url(os.environ["REDIS_URL"])

# Cache
r.setex("key", 3600, "value")  # 1 hour TTL
value = r.get("key")

# Session
r.hset(f"session:{session_id}", mapping={"user_id": "123", "role": "admin"})

# Rate limiting
key = f"ratelimit:{user_id}:{minute}"
count = r.incr(key)
r.expire(key, 60)
if count > 100:
    raise RateLimitExceeded()

# Job queue (BullMQ pattern)
r.xadd("jobs:inference", {"model": "zen-70b", "prompt": "Hello"})

Local Development (compose.yml)

services:
  postgres:
    image: postgres:16
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: hanzo
      POSTGRES_USER: hanzo
      POSTGRES_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  mongodb:
    image: mongo:7
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: hanzo
      MONGO_INITDB_ROOT_PASSWORD: "${MONGO_PASSWORD}"
    volumes:
      - mongo_data:/data/db

  s3:
    image: ghcr.io/hanzoai/s3:latest
    ports:
      - "9000:9000"
    command: server -s3 -s3.port=9000 -s3.config=/etc/hanzo/s3.json -dir=/data
    volumes:
      - s3_data:/data
      - ./s3.json:/etc/hanzo/s3.json:ro

volumes:
  postgres_data:
  redis_data:
  mongo_data:
  s3_data:

Troubleshooting

IssueCauseSolution
Port conflictService already runninglsof -i :5432 && kill PID
Connection refusedDB not starteddocker compose up -d postgres
pgvector not foundExtension not installedCREATE EXTENSION vector;
Slow queriesMissing indexAdd IVFFlat or HNSW index
OOMToo many connectionsConfigure max_connections
# Port conflicts
lsof -i :5432

# Full reset (destructive — loses all data)
docker compose down -v && docker system prune -a

# Connect to prod DB (from K8s pod)
kubectl exec -it postgres-0 -n hanzo -- psql -U hanzo
  • hanzo/hanzo-orm.md - Go ORM for database access
  • hanzo/hanzo-datastore.md - Vector database abstraction
  • hanzo/hanzo-stack.md - Local stack with all DBs
  • hanzo/hanzo-kms.md - Secret management (DB credentials)

How is this guide?

On this page