Access IRIS through the entire PostgreSQL ecosystem - Connect BI tools, Python frameworks, data pipelines, and thousands of PostgreSQL-compatible clients to InterSystems IRIS databases with zero code changes.
Connect any PostgreSQL-compatible tool to InterSystems IRIS without custom drivers:
- BI Tools: Apache Superset, Metabase, Grafana - zero configuration needed
- Python: psycopg3, pandas, Jupyter notebooks, FastAPI applications
- Data Engineering: DBT, Apache Airflow, Kafka Connect (JDBC)
- Programming Languages: Python, Node.js, Go, Java, .NET, Ruby, Rust, PHP
- pgvector Tools: LangChain, LlamaIndex, and other RAG frameworks
Connection String: postgresql://localhost:5432/USER - that's it!
git clone https://github.com/intersystems-community/iris-pgwire.git
cd iris-pgwire
docker-compose up -d
# Test it works
psql -h localhost -p 5432 -U _SYSTEM -d USER -c "SELECT 'Hello from IRIS!'"pip install iris-pgwire psycopg[binary]
# Configure IRIS connection
export IRIS_HOST=localhost IRIS_PORT=1972 IRIS_USERNAME=_SYSTEM IRIS_PASSWORD=SYS IRIS_NAMESPACE=USER
# Start server
python -m iris_pgwire.serverFor InterSystems IRIS 2024.1+ with ZPM package manager:
// Install the package
zpm "install iris-pgwire"
// Start the server manually
do ##class(IrisPGWire.Service).Start()
// Check server status
do ##class(IrisPGWire.Service).ShowStatus()From terminal:
# Install
iris session IRIS -U USER 'zpm "install iris-pgwire"'
# Start server
iris session IRIS -U USER 'do ##class(IrisPGWire.Service).Start()'import psycopg
with psycopg.connect('host=localhost port=5432 dbname=USER') as conn:
cur = conn.cursor()
cur.execute('SELECT COUNT(*) FROM YourTable')
print(f'Rows: {cur.fetchone()[0]}')Tested and verified with popular PostgreSQL clients:
| Language | Clients | Features |
|---|---|---|
| Python | psycopg3, asyncpg, SQLAlchemy (sync + async), pandas | Full CRUD, transactions, async/await, vector ops |
| Node.js | pg (node-postgres), Prisma, Sequelize | Prepared statements, connection pooling, ORM introspection |
| Java | PostgreSQL JDBC, Spring Data JPA, Hibernate | Enterprise ORM, connection pooling, batch operations |
| .NET | Npgsql, Entity Framework Core, Dapper | Async operations, LINQ queries, ORM support |
| Go | pgx, lib/pq, GORM | High performance, connection pooling, migrations |
| Ruby | pg gem, ActiveRecord, Sequel | Rails integration, migrations, ORM support |
| Rust | tokio-postgres, sqlx, diesel | Async operations, compile-time query checking |
| PHP | PDO PostgreSQL, Laravel, Doctrine | Web framework integration, ORM support |
| BI Tools | Apache Superset, Metabase, Grafana | Zero-config PostgreSQL connection |
Note: InterSystems is developing an official sqlalchemy-iris package that will be available in the intersystems-iris PyPI package, providing native IRIS SQLAlchemy support alongside PGWire compatibility.
Use Case: Your existing pgvector similarity search code works with IRIS - just change the connection string.
- Drop-in Syntax: Use familiar
<=>operator - auto-translated to IRIS VECTOR_COSINE - HNSW Indexes: 5Γ speedup on 100K+ vector datasets
- RAG-Ready: Compatible with LangChain, LlamaIndex embedding pipelines (1024D-4096D)
# pgvector syntax works unchanged with IRIS PGWire
import psycopg
with psycopg.connect("host=localhost port=5432 dbname=USER") as conn:
with conn.cursor() as cur:
# Similarity search with pgvector <=> operator
cur.execute(
"SELECT id, content FROM documents ORDER BY embedding <=> %s LIMIT 5",
(query_embedding,) # Python list - auto-converted
)
results = cur.fetchall()Use Case: Run Prisma, SQLAlchemy, and other ORMs against IRIS without configuration.
PostgreSQL ORMs expect tables in the public schema, but IRIS uses SQLUser. PGWire automatically maps between them:
# Prisma/SQLAlchemy queries work unchanged
# "SELECT * FROM public.users" β executes against SQLUser.users
# Results show table_schema='public' for ORM compatibility
import psycopg
with psycopg.connect("host=localhost port=5432 dbname=USER") as conn:
# This query returns IRIS SQLUser tables as 'public' schema
cur = conn.execute("""
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
""")
tables = cur.fetchall() # Your IRIS tables!Configuration (optional - defaults to SQLUser):
# For non-standard IRIS schema names
export PGWIRE_IRIS_SCHEMA=MyAppSchema# Or configure programmatically
from iris_pgwire.schema_mapper import configure_schema
configure_schema(iris_schema="MyAppSchema")Industry-standard security matching PgBouncer, YugabyteDB, Google Cloud PGAdapter:
- OAuth 2.0: Token-based authentication (cloud-native IAM)
- IRIS Wallet: Encrypted credential storage (zero plain-text passwords)
- SCRAM-SHA-256: Secure password authentication (industry best practice)
- Minimal Overhead: ~4ms protocol translation layer preserves IRIS native performance
- Dual Backend: External DBAPI (connection pooling) or Embedded Python (zero overhead)
- Async Python: Full async/await support with FastAPI and async SQLAlchemy
- Connection Pooling: 50+20 async connections, <1ms acquisition time
# Connect to IRIS via PostgreSQL protocol
psql -h localhost -p 5432 -U _SYSTEM -d USER
# Simple queries
SELECT * FROM MyTable LIMIT 10;
# Vector similarity search
SELECT id, VECTOR_COSINE(embedding, TO_VECTOR('[0.1,0.2,0.3]', DOUBLE)) AS score
FROM vectors
ORDER BY score DESC
LIMIT 5;import psycopg
with psycopg.connect('host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS') as conn:
# Simple query
with conn.cursor() as cur:
cur.execute('SELECT COUNT(*) FROM MyTable')
count = cur.fetchone()[0]
print(f'Total rows: {count}')
# Parameterized query
with conn.cursor() as cur:
cur.execute('SELECT * FROM MyTable WHERE id = %s', (42,))
row = cur.fetchone()
# Vector search with parameter binding
query_vector = [0.1, 0.2, 0.3] # Works with any embedding model
with conn.cursor() as cur:
cur.execute("""
SELECT id, VECTOR_COSINE(embedding, TO_VECTOR(%s, DOUBLE)) AS score
FROM vectors
ORDER BY score DESC
LIMIT 5
""", (query_vector,))
results = cur.fetchall()from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy import text
from fastapi import FastAPI, Depends
# Setup
engine = create_async_engine("postgresql+psycopg://localhost:5432/USER")
SessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
app = FastAPI()
async def get_db():
async with SessionLocal() as session:
yield session
# FastAPI endpoint with async IRIS query
@app.get("/users/{user_id}")
async def get_user(user_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(
text("SELECT * FROM users WHERE id = :id"),
{"id": user_id}
)
return result.fetchone()Industry-Standard Security - No plain-text passwords, enterprise-grade protection matching PgBouncer, YugabyteDB, Google Cloud PGAdapter.
# Standard PostgreSQL connection (SCRAM-SHA-256 secure authentication)
import psycopg
conn = psycopg.connect("host=localhost port=5432 user=_SYSTEM password=SYS dbname=USER")OAuth 2.0: Token-based authentication for BI tools and applications (cloud-native IAM pattern) IRIS Wallet: Encrypted credential storage with audit trail (zero plain-text passwords in code) SCRAM-SHA-256: Industry best practice for password authentication (replaces deprecated MD5)
See Authentication Guide for detailed configuration
All BI tools connect using standard PostgreSQL drivers - no IRIS-specific plugins required:
Connection Configuration:
Host: localhost
Port: 5432
Database: USER
Username: _SYSTEM
Password: SYS
Driver: PostgreSQL (standard)Modern data exploration and visualization platform.
docker-compose --profile bi-tools up superset
# Access: http://localhost:8088 (admin / admin)Try the Healthcare Demo: Complete working example with 250 patient records and 400 lab results - see Superset Healthcare Example for <10 minute setup.
User-friendly business intelligence tool with visual query builder.
docker-compose --profile bi-tools up metabase
# Access: http://localhost:3001Real-time monitoring and time-series visualization.
docker-compose up grafana
# Access: http://localhost:3000 (admin / admin)-- Semantic search directly in Superset/Metabase
SELECT id, title,
VECTOR_COSINE(embedding, TO_VECTOR('[0.1,0.2,...]', DOUBLE)) AS similarity
FROM documents
ORDER BY similarity DESC
LIMIT 10Protocol Translation Overhead: ~4ms (preserves IRIS native performance)
| Metric | Result | Notes |
|---|---|---|
| Simple Query Latency | 3.99ms avg, 4.29ms P95 | IRIS DBAPI baseline: 0.20ms |
| Vector Similarity (1024D) | 6.94ms avg, 8.05ms P95 | Binary parameter encoding |
| Binary Vector Encoding | 40% more compact | Efficient for high-dimensional embeddings |
| Connection Pool | 50+20 async connections | <1ms acquisition time |
| HNSW Index Speedup | 5.14Γ at 100K+ vectors | Requires β₯100K dataset |
Key Findings:
- β ~4ms protocol overhead enables entire PostgreSQL ecosystem
- β Binary parameter encoding (40% more compact than text)
- β 100% success rate across all dimensions and execution paths
Detailed Benchmarks: See benchmarks/README_4WAY.md and Vector Parameter Binding
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PostgreSQL Clients β
β (psql, DBeaver, Superset, psycopg3, JDBC, node-postgres, ...) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ Port 5432 (PostgreSQL Protocol)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β IRIS PGWire Server β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββββ β
β β Wire Proto β β Query β β Vector Translation β β
β β Handler ββββ Parser ββββ <=> β VECTOR_COSINE β β
β ββββββββββββββββ ββββββββββββββββ β <#> β VECTOR_DOT_PROD β β
β ββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ IRIS DBAPI / Embedded Python
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β InterSystems IRIS β
β (SQL Engine, Vector Support) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Feature | DBAPI Backend | Embedded Python Backend |
|---|---|---|
| Deployment | External Python process | Inside IRIS via irispython |
| Connection | TCP to IRIS:1972 | Direct in-process calls |
| Latency | +1-3ms network overhead | Near-zero overhead |
| Best For | Development, multi-IRIS | Production, max performance |
- Protocol Layer: PostgreSQL wire protocol v3 (message parsing, encoding)
- Query Translation: SQL rewriting, pgvector β IRIS vector functions
- Connection Pooling: Async pool with configurable limits (DBAPI backend)
Detailed Architecture: See Dual-Path Architecture
- IRIS Database: InterSystems IRIS 2024.1+ with vector support
- Python: 3.11+ (for development) or IRIS embedded Python
- Docker (optional): For containerized deployment
# Clone repository
git clone https://github.com/intersystems-community/iris-pgwire.git
cd iris-pgwire
# Start services
docker-compose up -d
# Verify services
docker-compose psPorts:
5432- PGWire server (PostgreSQL protocol)1972- IRIS SuperServer52773- IRIS Management Portal
# Install dependencies
pip install iris-pgwire intersystems-irispython psycopg[binary]
# Or with uv (recommended)
uv pip install iris-pgwire intersystems-irispython psycopg[binary]
# Configure IRIS connection
export IRIS_HOST=localhost
export IRIS_PORT=1972
export IRIS_USERNAME=_SYSTEM
export IRIS_PASSWORD=SYS
export IRIS_NAMESPACE=USER
# Optional: Configure schema mapping (default: SQLUser)
# export PGWIRE_IRIS_SCHEMA=MyAppSchema
# Start server
python -m iris_pgwire.server# From IRIS container/instance
export IRISUSERNAME=_SYSTEM
export IRISPASSWORD=SYS
export IRISNAMESPACE=USER
export BACKEND_TYPE=embedded
# Start embedded server
irispython -m iris_pgwire.serverBenefits: Zero network overhead, true VECTOR types, maximum performance
- Installation Guide - Detailed deployment instructions
- BI Tools Setup - Superset, Metabase, Grafana integration
- Developer Guide - Development setup and contribution
- Vector Parameter Binding - High-dimensional vector support
- DBAPI Backend Guide - Connection pooling configuration
- Testing Guide - Test framework and validation
- Dual-Path Architecture - DBAPI vs Embedded execution
- Embedded Python Servers - Running inside IRIS
- Client Compatibility - PostgreSQL client matrix
171/171 tests passing across 8 languages (Python, Node.js, Java, .NET, Go, Ruby, Rust, PHP)
β
Core Protocol: Simple queries, prepared statements, transactions, bulk operations (COPY)
β
Authentication: OAuth 2.0, IRIS Wallet, SCRAM-SHA-256 (no plain-text passwords)
β
Vectors: pgvector operators (<=> cosine, <#> dot product), HNSW indexes
β
Clients: Full compatibility with PostgreSQL drivers and ORMs
β
ORM Support: Schema mapping for Prisma, SQLAlchemy, and other ORM introspection tools
SSL/TLS: Delegated to reverse proxy (nginx/HAProxy) - industry-standard pattern matching QuestDB, Tailscale pgproxy Kerberos: Not implemented - matches PgBouncer, YugabyteDB, PGAdapter (use OAuth 2.0 instead)
See KNOWN_LIMITATIONS.md for detailed deployment guidance and industry comparison
# All tests (contract + integration)
pytest -v
# Specific categories
pytest tests/contract/ -v # Framework validation
pytest tests/integration/ -v # E2E workflows
# Vector parameter binding tests
python3 tests/test_all_vector_sizes.py # 128D-1024D validation
python3 tests/test_vector_limits.py # Maximum dimension testsConnection path latency comparison (50 iterations, 128-dimensional vectors):
| Connection Path | Simple SELECT | Vector Similarity | Best For |
|---|---|---|---|
| IRIS DBAPI Direct | 0.21ms | 2.35ms | Maximum performance |
| PGWire + DBAPI | 3.82ms | 6.76ms | PostgreSQL compatibility |
| PGWire + Embedded | 4.75ms | N/A | Single-container deployment |
| PostgreSQL (baseline) | 0.32ms | 0.59ms | Reference comparison |
Key Takeaways:
- IRIS DBAPI direct is ~18Γ faster than PGWire for simple queries
- PGWire adds ~4ms protocol translation overhead for PostgreSQL client compatibility
- For maximum performance, use IRIS DBAPI driver directly when PostgreSQL compatibility isn't required
Benchmarks from 2025-10-05. See benchmarks/README_4WAY.md for methodology.
Run Your Own Benchmarks:
# 4-way architecture comparison
./benchmarks/run_4way_benchmark.sh
# Custom parameters
python3 benchmarks/4way_comparison.py \
--iterations 100 \
--dimensions 1024 \
--output results.json# Clone repository
git clone https://github.com/intersystems-community/iris-pgwire.git
cd iris-pgwire
# Install development dependencies
uv sync --frozen
# Start development environment
docker-compose up -d
# Run tests
pytest -vCode Quality: black (formatter), ruff (linter), pytest (testing)
- Repository: https://github.com/intersystems-community/iris-pgwire
- IRIS Documentation: https://docs.intersystems.com/iris/
- PostgreSQL Protocol: https://www.postgresql.org/docs/current/protocol.html
- pgvector: https://github.com/pgvector/pgvector
MIT License - See LICENSE for details
- PostgreSQL wire protocol v3 (handshake, simple & extended query protocols)
- Authentication (SCRAM-SHA-256, OAuth 2.0, IRIS Wallet)
- Vector operations (pgvector syntax, HNSW indexes)
- COPY protocol (bulk import/export with CSV format, 600+ rows/sec)
- Transactions (BEGIN/COMMIT/ROLLBACK with savepoints)
- Async SQLAlchemy support (FastAPI integration, connection pooling)
- Dual backend architecture (DBAPI + Embedded Python)
- Multi-language client compatibility (8 drivers at 100%: Python, Node.js, Java, .NET, Go, Ruby, Rust, PHP)
- ORM schema mapping (
publicβ configurable IRIS schema for Prisma, SQLAlchemy introspection)
Note: These limitations are common across PostgreSQL wire protocol implementations. For example, PgBouncer also omits GSSAPI support, and QuestDB does not support SSL/TLS.
- SSL/TLS wire protocol: Not implemented - use reverse proxy (nginx/HAProxy) for transport encryption
- Kerberos/GSSAPI: Not implemented - use OAuth 2.0 or IRIS Wallet instead
- Cosine distance (
<=>): β Supported βVECTOR_COSINE() - Dot product (
<#>): β Supported βVECTOR_DOT_PRODUCT() - L2/Euclidean (
<->): β Not implemented
- System catalogs:
pg_type,pg_catalognot available (IRIS uses INFORMATION_SCHEMA) - CREATE EXTENSION: Not supported (IRIS has native vector support)
| Category | Won't Work (via PGWire) | IRIS-Native Alternative |
|---|---|---|
| LangChain | langchain_community.PGVector |
langchain-iris (PyPI) |
| LlamaIndex | llama_index.PGVectorStore |
llama-iris (PyPI) |
| Haystack | haystack.PGVector |
psycopg3 with custom retriever |
| ORM/Database | SQLAlchemy + psycopg2 | psycopg3 directly |
| Admin Tools | pgAdmin (full features) | IRIS Management Portal |
# Install IRIS-native LangChain/LlamaIndex integrations
pip install langchain-iris llama-iris# LangChain with native IRIS connection
from langchain_iris import IRISVector
db = IRISVector(
embedding_function=embeddings,
connection_string="iris://_SYSTEM:SYS@localhost:1972/USER",
collection_name="my_docs"
)
db.add_texts(["Document 1", "Document 2"])
results = db.similarity_search("query", k=5)For direct PostgreSQL wire protocol access:
import psycopg
with psycopg.connect("host=localhost port=5432 dbname=USER") as conn:
cur.execute("SELECT * FROM docs ORDER BY embedding <=> %s LIMIT 5", (query_vec,))- SSL/TLS wire protocol encryption
- Kerberos/GSSAPI authentication
- Connection limits & rate limiting
- Performance optimization (executemany() for bulk operations)
- Advanced PostgreSQL features (CTEs, window functions)
Questions? File an issue on GitHub