HeliosProxy is a programmable PostgreSQL data-plane: a wire-protocol connection router that pools connections, splits reads from writes, and keeps client sessions alive through a primary failure with Transaction Replay. It adds a WASM plugin runtime, operator-driven traffic replay and a major-version upgrade orchestrator, runs in front of any PostgreSQL-wire backend, and is licensed Apache 2.0.
Last updated
Ships an AGENTS.md aggregate plus a .claude/skills/ catalogue. Every CLI flag, REPL meta-command, public API, and MCP tool indexed for LLM coding agents. cargo install heliosdb-proxy builds the default feature set (pooling modes and Transaction Replay); add --features all-features for the optional modules, which the GHCR image and the release binaries already include. Read the guide →
cargo install heliosdb-proxy
heliosdb-proxy install skills
This is the largest release in HeliosProxy's history. The proxy is no longer a router with feature flags — it is a programmable data-plane with a real WASM runtime, signed plugins distributed via OCI, time-travel replay over a transaction journal, a zero-downtime PostgreSQL major-version upgrade orchestrator, and a built-in admin web console. All 24 connection-routing feature modules remain.
Wasmtime executes signed plugins inside the proxy. Five hook points — Authenticate, Route, PreQuery, PostQuery, Validate — each can rewrite, augment, or block. RouteResult::Block denies queries before they hit a backend.
Plugin signature verification at load time. SignatureVerifier wired into the runtime config. Distribution via .tar.gz OCI artefacts pulled from any OCI registry — sign, push, deploy.
Replay any window of historical traffic against the current cluster, a standby, or a candidate. Per-call credential overrides; admin /api/replay; built-in UI form. TransactionJournal is auto-attached in ServerState.
Real SQL stage bodies execute on a tick schedule. Shadow-execution comparator runs traffic against both the old and new backend, diffing results before the cut. The hardest operational task on Postgres, orchestrated by the proxy.
Real PG connection pool, pg_is_in_recovery() polling, pg_promote + WAL probe sync-wait, real statement replay against the replacement primary, and simple-protocol SET state restored transactionally. Cursors, PREPAREd statements and temp tables are not restored — see the refusal list below.
Static admin web UI at /. Topology, plugins, chaos mode, shadow execution, time-travel replay — all first-class panels. No separate admin tool to deploy or secure.
HeliosProxy is licensed under Apache 2.0. Permissive, OSI-approved, and aligned with HeliosDB Nano — use it freely in commercial, managed-service, and proprietary deployments without copyleft obligations.
Plugins are not configuration. They are real WebAssembly modules executing inside the proxy with sandboxed wasmtime, fuel-metered execution, and bounded memory. Five hook points cover authentication, routing, query lifecycle, and validation. Authoring is one Rust crate; deployment is one signed OCI artefact.
Authenticate, Route, PreQuery, PostQuery, Validate. Each can short-circuit, rewrite, deny, or augment.SignatureVerifier enforces signatures at load time. cargo helios-plugin sign is the publisher path..tar.gz artefacts pulled from any OCI registry; the loader handles unpacking and signature verification end-to-end.env.sha256_hex. Plugins can do real work without escaping the sandbox.RouteResult::Block denies a query at the routing stage and returns a structured reason to the client.# 1. Author the plugin (Rust crate, compile to wasm32-wasi)
cargo build --release --target wasm32-wasi
# 2. Sign with your Ed25519 key
cargo helios-plugin sign \
--key ./signing.key \
--input target/wasm32-wasi/release/auth_plugin.wasm
# 3. Push to any OCI registry
oras push registry.example.com/my-org/auth-plugin:v1 \
./auth_plugin.wasm.tar.gz
# 4. Reference in heliosproxy.toml
[[plugins]]
name = "auth"
source = "oci://registry.example.com/my-org/auth-plugin:v1"
hooks = ["Authenticate", "PreQuery"]
verify_with = "./trusted-keys.toml"
With Transaction Replay, which keeps client sessions alive through a primary failure: sessions re-home and restore state, an interrupted read re-runs when it is provably side-effect-free, and opt-in transaction mode replays uncommitted work on the new primary — verifying every replayed result against what the client already saw.
No cargo feature, no application change. Transaction Replay ships in the default build — in-session recovery, the recovery journal and the operator-driven /api/replay and /api/shadow endpoints — for any PostgreSQL-wire client and any PG-wire backend. tr_enabled in proxy.toml switches it on or off at runtime; the old ha-tr feature is a deprecated no-op (Transaction Replay docs).
tr_mode selects how much the proxy does on your behalf when the primary fails. Each level includes the one before it:
none — the client gets a proper PostgreSQL error (SQLSTATE 57P01) and the connection closes.session (default) — the connection stays alive; the proxy re-homes it to the new primary and replays the session's tracked SET/RESET state. The interrupted statement returns one error (57P01 if it never reached the old primary, 08007 if its outcome is unknown); not-yet-delivered autocommit statements are re-executed transparently.select — additionally re-runs an interrupted read, but only when every function it calls is provably side-effect-free — a PostgreSQL built-in on the proxy's allowlist, or a name you added to tr_read_functions. A read calling a user-defined function, nextval, pg_notify, set_config or an advisory lock is opaque: it returns 08007 and is never run a second time.transaction (opt-in) — additionally replays the uncommitted transaction from its BEGIN on the new primary. Replay is verified: each statement's original response frames were digested as the client saw them, the replacement backend's responses are digested the same way, and any divergence rolls the replay back with 40001 rather than continuing on top of rows the client never observed.Session state. SET/RESET tracking is transactional and savepoint-scoped, mirroring PostgreSQL: a SET inside a transaction takes effect for restore only if that transaction commits, and ROLLBACK TO SAVEPOINT discards the ones issued after the savepoint. It covers simple-protocol statements only — extended-protocol SETs as sent by JDBC, SQL-level PREPARE, session temp tables and open cursors are not restored.
One deadline. write_timeout_secs bounds the entire recovery — waiting for a healthy primary, connect and auth, session-state restore, replay and re-execution — instead of each phase carrying its own timeout that could add up past the configured value. Failing over onto password-protected backends needs the proxy as the auth boundary ([auth] mode = "scram").
Verified live against PostgreSQL 18.4: a 77-check failover battery across all four modes, plus a 7-case commit-outcome suite and a 13-case streaming suite that the pre-fix binary failed 4 and 12 of respectively. Full behaviour reference →
# In-session failover — core, no cargo feature
tr_enabled = true
tr_mode = "session" # none | session | select | transaction
write_timeout_secs = 30 # one deadline for the whole recovery
tr_read_functions = [] # extra provably-pure functions
[auth]
mode = "scram" # proxy is the auth boundary
[limits]
tr_max_replay_statements = 1000
tr_max_replay_bytes = 16777216
tr_max_session_set_statements = 256
tr_max_observation_bytes = 1048576 # replay-verification digest
max_backend_frame_bytes = 104857600 # bounds one backend frame
backend_response_timeout_secs = 0 # 0 = off; bounds a slow drip
# Prometheus (/metrics)
# tr_failovers_total
# tr_statements_reexecuted_total
# tr_transactions_replayed_total
# tr_replay_failures_total
# tr_unknown_outcome_errors_total
Every transaction the proxy sees is journalled. Replay any window of historical traffic against the current cluster, a standby, or a brand-new candidate — with optional per-call credential overrides for security validation and migration rehearsal. The shadow-execution comparator runs the same traffic against two backends side-by-side and diffs the result, catching divergence before a cut.
TransactionJournal auto-attached to ServerState; no separate storage to provision.POST /api/replay for automation; the admin UI ships a built-in form for operator-driven replays.A as user B. Useful for security validation and migration rehearsal.# Replay last hour against a candidate node
curl -X POST http://proxy:9090/api/replay \
-H "Content-Type: application/json" \
-d '{
"mode": "time_window",
"from": "2026-04-26T10:00:00Z",
"to": "2026-04-26T11:00:00Z",
"target_host": "candidate-pg17",
"target_port": 5432,
"target_user": "audit_replay",
"target_password": "...",
"target_database": "app"
}'
# Returns: mode, statements_replayed, failures,
# partial, deadline_exceeded, elapsed_ms, from,
# to, first_error, coverage
The hardest operational task on Postgres — major-version upgrades — is now coordinated by the proxy. Real SQL stage bodies execute on a tick schedule against both the old and new instances. The chaos-mode admin endpoint injects controlled failures during rehearsal. The shadow-execution comparator validates that the new backend produces equivalent results before traffic moves.
/api/chaos + UI panel inject failure scenarios so you find issues in pre-prod, not in the cut window.[upgrade]
enabled = true
from_backend = "pg12-prod"
to_backend = "pg17-candidate"
shadow_window = "24h"
cut_threshold = 0 # max diff rows
[[upgrade.stages]]
name = "backfill"
tick = "30s"
sql = """
INSERT INTO pg17.events
SELECT * FROM pg12.events
WHERE id > (SELECT COALESCE(MAX(id), 0) FROM pg17.events)
LIMIT 10000
"""
[[upgrade.stages]]
name = "verify"
tick = "5m"
sql = "SELECT COUNT(*) FROM pg17.events"
A static admin web UI ships with the proxy at the root path. No separate admin service to deploy, no extra service to secure, no second auth model to keep in sync. Topology, plugins, chaos mode, shadow execution, and time-travel replay are all first-class panels.
Auth: shares the proxy's existing admin auth model (JWT or API key). The UI is static HTML/JS served from the same binary — no Node.js, no build step, no second container.
# Topology
GET /api/topology
GET /api/health
# Plugins
GET /plugins
POST /plugins/{id}/reload
POST /plugins/{id}/disable
# Chaos mode
POST /api/chaos
GET /api/chaos/active
# Time-travel replay
POST /api/replay
GET /api/replay/{id}
# Shadow execution
POST /api/shadow/start
GET /api/shadow/{id}/diff
Earlier this month: pool-checkout 28–37% faster and 3.1× faster metrics reads (internal tests, HeliosProxy 0.3.1 vs 0.3.0, see the release notes), zero-allocation protocol parsing, concurrent L1 cache hits. Still in the latest release. Full release notes →
Idle-connection pop and semaphore acquire happen outside the map lock. Per-node state is held behind a cheap cloneable Arc<Semaphore>, so concurrent checkouts to different backends no longer contend.
Acquires, timeouts, connections created/closed, recycles, and validation failures are atomic. Reading the full pool.metrics() snapshot is sub-15 ns and never contends with checkouts.
Prepared-statement parameter values are handled as reference-counted slices into the original protocol buffer — no per-parameter heap allocation during parse. C-string reads use a single scan rather than incremental buffer growth.
Cache hits take a read lock and bump an atomic per-entry access counter, so many threads can hit the same cached query in parallel without serialising. Covered by a 16-thread × 500-iteration regression test.
Method: cargo bench --bench pooling -- --quick, same machine, single-threaded, criterion quick mode. Directional indicator of request-path cost — the pool is one component; full-proxy QPS depends on backend, workload, and network.
Use HeliosProxy when client sessions must survive a primary failure: PgBouncer pools connections but does not handle failover, so its clients see errors, while HeliosProxy re-homes each session to the new primary and restores its state (failover demo). Both pool in session, transaction and statement modes; HeliosProxy adds read/write splitting and health checks, with circuit breaking, caching, rate limiting and WASM plugins as optional build features.
| Challenge | Without Proxy | With HeliosProxy |
|---|---|---|
| Connection limits | App manages pools | Automatic pooling |
| Query caching | Manual Redis / Memcached | Built-in 3-tier cache |
| Rate limiting | External service | Native support |
| Multi-tenancy routing | App logic | Automatic routing |
| Circuit breaking | Manual implementation | Built-in resilience |
| GraphQL API | Separate gateway | Auto-generated |
| Authentication | Custom middleware | JWT, OAuth, LDAP, API Keys |
Three modes to match your workload. HeliosProxy's transaction and statement pooling modes let many client connections share a bounded pool of backend connections per user and database; the achievable ratio depends on the workload, so measure it on your own traffic. Session mode is the default, and pools are kept per node, user and database, so distinct users never share a backend connection.
# Transaction pooling: many clients share a
# bounded pool per node, user and database
[pool_mode]
mode = "transaction" # session (default) | transaction | statement
max_pool_size = 100 # backend connections per node
min_idle = 10
reset_query = "DISCARD ALL"
[limits]
max_client_connections = 5000 # 0 = off (default)
Only when you enable it: the query cache is an opt-in build feature and is off by default. Once on, it serves repeated SELECT results and drops them when a write through the proxy commits. Writes that bypass the proxy show up only when an entry's TTL expires, and cached results are not keyed by session state, so leave the cache off where row-level security reads per-session settings (configuration reference).
Automatic cache invalidation on writes. Configurable exclusion patterns for INSERT, UPDATE, and DELETE statements.
-- Repeated reads are served from L1
SELECT * FROM users
WHERE id = 42;
# Cache configuration (query-cache build)
[cache]
enabled = true
ttl_secs = 60
max_result_bytes = 1048576
HeliosProxy includes an optional GraphQL-to-SQL gateway: an HTTP listener that answers flat top-level queries over configured tables. It is off by default and needs the graphql-gateway build feature, which the GHCR image and the release binaries include.
# Flat top-level selection
query {
users {
id
email
}
}
# Enable in proxy.toml:
# [graphql_gateway]
# enabled = true
Extend HeliosProxy with custom WebAssembly plugins. Write your logic in Rust, Go, or any language that compiles to WASM, and inject it into the query pipeline at any hook point.
use wasm_bindgen::prelude::*;
// Custom query rewriting plugin
#[wasm_bindgen]
pub fn rewrite_query(
query: &str,
context: &Context
) -> String {
// Add tenant filter to all queries
if !query.contains("tenant_id") {
query.replace(
"WHERE",
&format!(
"WHERE tenant_id = {} AND",
context.tenant_id
)
)
} else {
query.to_string()
}
}
# Plugin configuration
# [plugins.wasm]
# name = "tenant-filter"
# path = "/plugins/tenant_filter.wasm"
# hook = "query_rewrite"
HeliosProxy automatically classifies and routes queries to the optimal backend. Lag-aware read replicas, circuit breaker protection, and workload-based routing ensure every query hits the best target.
# Workload-based routing
[routing]
schema_aware = true
[routing.workload]
enabled = true
# OLTP queries -> primary
oltp_patterns = [
"SELECT * FROM users WHERE id",
"INSERT INTO orders"
]
oltp_target = "primary"
# OLAP queries -> analytics replica
olap_patterns = [
"SELECT.*GROUP BY",
"SELECT.*ORDER BY.*LIMIT"
]
olap_target = "analytics"
# Vector queries -> vector node
vector_patterns = [
"ORDER BY.*<=>",
"embedding.*<->"
]
vector_target = "vector-node"
# Circuit breaker
[circuit_breaker]
enabled = true
failure_threshold = 5
reset_timeout = "30s"
half_open_requests = 3
HeliosProxy inspects and optimizes queries before they reach the database. Automatic rewriting improves performance without any application code changes.
# AI workload optimization
[ai_cache]
enabled = true
# Conversation context cache
conversation_context_ttl = "30m"
conversation_context_size = "512MB"
# RAG chunk cache
rag_chunk_cache_size = "2GB"
rag_chunk_ttl = "1h"
# Semantic query cache
semantic_cache_enabled = true
similarity_threshold = 0.92
# Query cache control
[cache.query]
enabled = true
max_result_size = "10MB"
exclude_patterns = [
"INSERT",
"UPDATE",
"DELETE"
]
Centralized authentication before database access. Support for JWT, OAuth 2.0, LDAP, and API keys — all validated at the proxy layer before any query reaches the database. HeliosProxy uses classical TLS key exchange today; post-quantum key exchange is planned.
[auth]
enabled = true
# JWT validation
[auth.jwt]
enabled = true
issuer = "https://auth.example.com"
audience = "heliosdb"
jwks_url = "https://auth.example.com/.well-known/jwks.json"
# Extract tenant from JWT claims
tenant_claim = "org_id"
role_claim = "db_role"
# API key validation
[auth.api_key]
enabled = true
header = "X-API-Key"
# LDAP integration
[auth.ldap]
enabled = true
server = "ldap://ldap.example.com:389"
base_dn = "dc=example,dc=com"
Flexible tenant isolation strategies to match your architecture. From shared-database with Row-Level Security to dedicated databases per tenant — HeliosProxy handles routing, resource limits, and isolation transparently.
[tenancy]
enabled = true
tenant_header = "X-Tenant-ID"
default_tenant = "public"
# Enterprise tenant: dedicated DB
[[tenancy.tenant]]
id = "enterprise-1"
database = "enterprise_1"
pool_size = 100
cache_size = "2GB"
# Startup tenant: shared DB
[[tenancy.tenant]]
id = "startup-tier"
database = "shared"
pool_size = 10
cache_size = "256MB"
rate_limit_qps = 100
Track and analyze every query pattern flowing through HeliosProxy. Identify slow queries, monitor cache efficiency, and understand your workload — all with built-in analytics.
pool.metrics() snapshots read in sub-15 ns and never contend with checkouts.-- Top 20 slowest queries
SELECT query_pattern,
avg_duration,
call_count
FROM heliosproxy_query_stats
ORDER BY avg_duration DESC
LIMIT 20;
-- Most frequent queries + cache hits
SELECT query_pattern,
call_count,
cache_hit_rate
FROM heliosproxy_query_stats
ORDER BY call_count DESC
LIMIT 20;
-- Overall cache efficiency
SELECT
SUM(cache_hits) AS hits,
SUM(cache_misses) AS misses,
ROUND(
SUM(cache_hits)::float /
(SUM(cache_hits) + SUM(cache_misses)),
3
) AS hit_rate
FROM heliosproxy_cache_stats;
Protect your database from overload with granular rate limiting at every level. Global limits, per-tenant quotas, per-user throttling, and per-query cost limits — all enforced at the proxy layer.
[rate_limit]
enabled = true
# Global limits
global_qps = 10000
global_connections = 5000
# Enterprise customer
[[rate_limit.tenant]]
id = "enterprise-customer"
qps = 2000
connections = 500
# Free tier
[[rate_limit.tenant]]
id = "free-tier"
qps = 100
connections = 10
burst = 20
# Client-side handling
try:
cursor.execute("SELECT * FROM users")
except HeliosError as e:
if e.code == "RATE_LIMIT_EXCEEDED":
time.sleep(e.retry_after)
Call POST /api/replay on the admin API: it re-executes transactions from the proxy's recovery journal against a target backend you name, such as a staging copy. The journal ships in the default build with Transaction Replay and records the transactions the proxy saw commit. None of it sits on the path a live client takes through a failover.
BEGIN/COMMIT boundaries, per-statement outcomes, savepoint structure and bound parameter values. Rolled-back transactions and rejected statements never enter it, and reads are not journaled.[journal] dir it lives in process memory and nothing survives a restart; with it, committed transactions are also appended to CRC-checked segment files that are reloaded at startup.mode: "time_window" (the default) re-executes the committed statements of a [from, to] window one by one, best effort. "Re-run yesterday 10:00–11:00 against staging."mode: "committed_history" applies each committed transaction in commit order in its own BEGIN … COMMIT, stops at the first failure and returns last_commit_seq so the next call can resume.POST /api/shadow runs a query against a source and a shadow backend in parallel and diffs the results: upgrade validation, migration canaries, replica-drift detection.Details: recovery journal and committed-history replay, the replay endpoint.
# Keep the journal across restarts (optional)
[journal]
dir = "/var/lib/heliosproxy/journal"
# Replay committed history against staging
curl -X POST localhost:9090/api/replay \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
--data @replay-window.json
# => {"mode": "committed_history",
# "transactions_replayed": 12,
# "last_commit_seq": 1042, ...}
# Diff one query across two backends
curl -X POST localhost:9090/api/shadow \
-H "Authorization: Bearer $ADMIN_TOKEN" \
--data @shadow-request.json
# With tr_enabled = false, /api/replay
# answers 503 and journaling stops.
HeliosProxy never retries a COMMIT whose outcome is unknown, never replays a SERIALIZABLE or REPEATABLE READ transaction and never runs an opaque read twice; each refusal returns a specific SQLSTATE instead of a guess. Transparent recovery is the goal; a clear error is the fallback; a wrong answer is never acceptable. These refusals are the feature.
COMMIT outcome is never retried — the client gets 08007 and guidance to verify. This covers COMMIT, END, PREPARE TRANSACTION and COMMIT PREPARED.SERIALIZABLE or REPEATABLE READ, whether set on BEGIN, via SET TRANSACTION, or inherited from default_transaction_isolation. No replacement backend can reproduce that snapshot.[limits] tr_max_observation_bytes has no digest to verify against, so its transaction is marked non-replayable.08006, rather than re-homing a session with half its settings.40001 — the replay rolls back instead of continuing on rows the client never saw.08007.COPY in progress at the fault — 08006, connection closed.Verification catches divergent results; it does not create determinism. Replay will not make now(), random() or a RETURNING serial reproduce their first values — which is why transaction mode is opt-in.
-- The backend died mid-transaction.
-- Recovery succeeded, verified:
COMMIT;
-- (no error; a slow query, not a drop)
-- Replayed rows did not match what
-- this client already saw:
-- ERROR: 40001 serialization_failure
-- replay verification failed;
-- transaction rolled back
-- The COMMIT may or may not have landed:
-- ERROR: 08007
-- transaction_resolution_unknown
-- verify before retrying
-- Session state could not be restored:
-- ERROR: 08006 connection_failure
-- Never restored across a failover:
-- SQL-level PREPAREd statements
-- session temp tables
-- open cursors
-- advisory locks
-- extended-protocol SETs (JDBC)
Simple-protocol SET and RESET state survives a failover, and protocol-level named prepared statements are re-prepared on the new primary when next used; SQL-level PREPARE statements, temporary tables, open cursors and advisory locks do not (transaction replay). Re-homing a session means opening a fresh backend connection, so session state has to be rebuilt on the new primary. HeliosProxy restores the part it can track correctly, and is explicit about the rest.
SET/RESET — tracked per session and replayed in order onto the replacement backend. Covers timezone, search_path, client_encoding, datestyle, application_name and arbitrary custom variables.SET inside a transaction takes effect for restore only when that transaction commits; ROLLBACK discards it. RESET, RESET ALL and DISCARD ALL inside a transaction are deferred to commit, so a rolled-back RESET ALL no longer wipes the restore set.ROLLBACK TO SAVEPOINT discards the SETs issued after that savepoint; RELEASE keeps them.SET reuses its slot instead of consuming another. [limits] tr_max_session_set_statements (default 256) counts distinct variables; exceeding it refuses the failover with 08006.PREPAREd statements, session temp tables, open cursors and advisory locks. Applications depending on that state surviving a failover still need application-level coordination.SETs issued through the extended query protocol, as most JDBC drivers send them. SET LOCAL, SET TRANSACTION and SET CONSTRAINTS are transaction-scoped by definition and never tracked.-- Tracked as the session runs
SET timezone TO 'America/New_York';
SET search_path TO myapp, public;
SET app.tenant_id TO '42';
BEGIN;
SET statement_timeout TO '5s';
SAVEPOINT sp1;
SET work_mem TO '256MB';
ROLLBACK TO sp1; -- work_mem dropped
COMMIT; -- statement_timeout kept
-- Primary dies. On the new backend the
-- proxy replays exactly the surviving set:
-- SET timezone TO 'America/New_York'
-- SET search_path TO myapp, public
-- SET app.tenant_id TO '42'
-- SET statement_timeout TO '5s'
-- Had that COMMIT been a ROLLBACK,
-- statement_timeout would not be restored.
-- Over 256 distinct variables, the
-- failover is refused outright:
-- ERROR: 08006 connection_failure
Connect to any node — primary or standby — and HeliosProxy automatically routes write operations to the current primary. Applications never need to track topology changes, enabling true connect-anywhere simplicity with zero client-side routing logic.
# Transparent Write Routing
[transparent_write_routing]
enabled = true
sync_mode = "sync"
forward_timeout_ms = 5000
[transparent_write_routing.pool]
max_connections = 50
idle_timeout_ms = 60000
health_check_interval_ms = 5000
-- App connects to ANY node (standby)
-- Reads stay local, writes auto-route
SELECT * FROM orders
WHERE user_id = 42;
-- → executes on standby (local)
INSERT INTO orders (user_id, total)
VALUES (42, 149.99);
-- → auto-forwarded to primary
-- → sync: confirmed on standby
24 connection-routing capabilities + 22 platform capabilities (plugin-host extensions, admin surface, first-party plugins, companion projects). The optional ones map to 21 build features: the default build has the pooling modes and Transaction Replay, and the GHCR image and release binaries are built with all of them.
Session (default), Transaction and Statement modes with prepared statement forwarding; the multiplexing ratio depends on the workload.
Round-robin, least-connections, or latency-based distribution. Automatic read/write splitting.
Configurable health-check queries, failure thresholds, and automatic node removal/recovery.
PostgreSQL extended query protocol pipelining. Batches Parse, Bind, Execute to reduce round trips. Parameter values parsed as zero-copy slices into the protocol buffer.
Auto-coalesces individual INSERTs into multi-row batches for higher write throughput.
Automatic failover with promotion policies. Prefers sync standbys, ranks by replication lag.
Core, no build flag. Replays the uncommitted transaction on the new primary and verifies every replayed response against what the client already saw.
Replays simple-protocol SET/RESET onto the replacement backend, transactionally and savepoint-scoped. PREPARE, temp tables and cursors are not restored.
Digests each response as the client saw it and re-checks it on replay. Divergence rolls back with SQLSTATE 40001 instead of continuing on unseen rows.
Buffers incoming queries during failover and drains to the new primary. Increased latency, not errors.
Pluggable topology discovery: PostgreSQL polling, HeliosDB native events, or manual via Admin API.
Write-ahead journal for in-flight transactions with statement-level granularity and parameter capture.
Two-tier result cache: L1 hot (sub-μs), L2 warm (TTL-based, keyed by normalized query fingerprints); a semantic tier is planned.
Embed routing directives in SQL comments: /*+ route=primary */, /*+ route=nearest */.
Routes reads to replicas within a configurable lag threshold. Includes read-your-writes consistency.
Rule-based SQL transformations: add hints, inject filters, redirect tables, enforce naming conventions.
Fingerprinting, slow query log, intent classification (OLTP/analytics/vector), N+1 detection.
Data temperature classification (hot/warm/cold), workload-type detection, automatic schema discovery.
JWT, OAuth 2.0, LDAP, API key validation, and external identity claim-to-role mapping.
Token bucket, sliding window, and concurrency limiting. Per-tenant, per-user, per-IP, per-query cost.
Adaptive failure detection with closed/open/half-open states and automatic recovery probes.
Tenant identification, pool isolation, schema routing, and per-tenant resource quotas.
Extend with sandboxed WebAssembly plugins. Hot-reloadable, memory-limited, controlled host API.
Auto-generated GraphQL API from schema with DataLoader batching and query validation.
In-process detector for rate spikes (z-score against rolling EWMA), credential-stuffing bursts, six classes of SQL-injection patterns, and novel query shapes. No external SIEM — events stream over /anomalies.
Cache-first proxy for geo-distributed deployments. Local LRU+TTL+version cache on every edge; home broadcasts table-scoped invalidations on writes. Last-write-wins, no consensus.
env.kv_get/kv_set/kv_delete wasmtime imports. Per-plugin namespaced state that survives across hook invocations. Counters, budgets, signatures persist without per-call data round-trips.
env.sha256_hex host import backed by the audited sha2 crate. Plugins compute real SHA-256 without embedding the algorithm (~25 KiB saved per .wasm).
Optional Ed25519 trust root: drop *.pub files in a directory and every loaded .wasm requires a verifying .sig sidecar. Interoperates with openssl/signify.
.tar.gz distribution format with manifest.json + plugin.wasm + optional plugin.sig. The proxy loader detects .gz extension and ingests directly.
RouteResult::Block { reason } ABI variant for hard-rejecting queries from a Route-hook plugin. Wire-compatible with PreQueryResult::Block — clients see one consistent error format.
[plugins].trust_root = "/path/to/keys" in proxy.toml. Auto-attaches the SignatureVerifier when set; defaults to permissive when unset (dev-loop ergonomics preserved).
Single embedded HTML dashboard at / and /ui on the admin port. Ten panels (Nodes, Topology, Plugins, Anomalies, Edge Mode, Chaos Mode, Shadow Execution, Time-Travel Replay, SQL, Traffic). Auto-refresh every 5 s. No build step.
Eight new endpoints surface every platform capability: /topology, /plugins, /anomalies, /api/edge*, /api/chaos, /api/shadow, /api/replay. Operator + UI consume the same JSON.
Per-tenant query cost budgets (minute / hour / day windows). Sliding window stored in the plugin's KV namespace; thresholds per tenant via the operator's TenantQuota CRD.
Detects LLM-generated SQL via application_name keywords, generated-by markers, opt-in attributes. Best-effort agent_id + model_id extraction. Persists per-request tags into KV for downstream plugins.
Per-(agent, model) cost gating for AI traffic. Sliding-window (minute + day) tracked in KV; blocks when budget exhausted. Cost model assumes ~4 bytes per token.
Refuses dangerous SQL from AI traffic: DROP/TRUNCATE, DELETE/UPDATE without WHERE, SELECT without LIMIT against large tables, missing tenant_id filter. Self-contained — useful even without ai-classifier deployed.
Routes pgvector top-K queries (<->, <#>, <=> in ORDER BY) to a topology-tagged vector replica. Falls back to default routing when no tagged node exists.
Per-role column masking via SQL rewriting. SELECT ssn becomes SELECT mask_ssn(ssn) AS ssn when the user lacks the pii_reader role. Idempotent on re-application.
Hash-chained tamper-evident audit log. Every query record embeds SHA-256 of the previous; modifying any entry breaks the chain. Real cryptography via env.sha256_hex (previously a placeholder).
Per-user data-residency routing. Reads user region from helios.region attribute; routes to a tagged in-region replica or returns RouteResult::Block with a proper PG ErrorResponse when no in-region node exists.
helios-plugin CLIPack, inspect, and verify WASM plugin artefacts as portable .tar.gz. Same Ed25519 trust-root format as the proxy loader. Interoperates with openssl/signify.
CRDs for HeliosProxy, PoolProfile, RoutingRule, AuditPolicy, TenantQuota. Reconciler renders ConfigMap + Deployment + Service per CR; polls /topology to populate status. Owned objects auto-clean on kubectl delete.
Five resources mirror the operator CRDs: heliosproxy_instance, _pool_profile, _routing_rule, _audit_policy, _tenant_quota. Schema generated from the operator's Go types via local replace.
Wraps the Terraform provider via pulumi-terraform-bridge. Same five resources surfaced as first-class Pulumi types in TypeScript / Python / Go / .NET.
| Repository | Purpose | Access |
|---|---|---|
HeliosDatabase/HeliosDB-Proxy | Core proxy | Public → |
HeliosDatabase/HeliosDB-Proxy-Operator | Kubernetes operator | Private |
HeliosDatabase/HeliosDB-Proxy-Plugins | First-party WASM plugins + CLI | Public → |
HeliosDatabase/terraform-provider-HeliosDB-Proxy | Terraform provider | Private |
HeliosDatabase/pulumi-HeliosDB-Proxy | Pulumi provider | Private |
ghcr.io/heliosdatabase/hdb-heliosdb-proxy:2.1.0 | Container image (lowercase — GHCR convention) | Public → |
Internal tests, HeliosProxy pooled and cached vs direct PostgreSQL connections. The figures are workload-dependent; reproduce them on your own hardware and workload.
vs. 8.2K direct connection. 5x throughput improvement from connection pooling alone.
L1 hot cache serves frequently accessed results in sub-millisecond time.
vs. 12ms direct connection establishment. 40x faster via connection pooling.
Automatic failover with Transaction Replay. Where recovery is possible, clients experience a brief pause rather than an error; where it is not, a specific SQLSTATE.
HeliosProxy operates at the wire protocol level. All features work transparently with any PostgreSQL-wire-compatible database.
| Backend | Compatibility | Notes |
|---|---|---|
| PostgreSQL 12+ | Full | Including Amazon RDS, Aurora, Cloud SQL, Azure Database |
| HeliosDB Lite | Full | Bundled inside Lite builds; a standalone HeliosProxy uses static topology for Lite nodes |
| HeliosDB Full | Full | PostgreSQL-wire pooling and routing; Full runs as a single server today, so failover applies once Full clustering ships (planned) |
| CockroachDB | Full | PostgreSQL wire protocol compatible |
| YugabyteDB | Full | PostgreSQL wire protocol compatible |
| TimescaleDB | Full | Runs as PostgreSQL extension |
| Citus | Full | Runs as PostgreSQL extension |
| AlloyDB | Full | Google Cloud PostgreSQL-compatible |
HeliosProxy isn’t just a connection pooler — it’s an AI-native database platform layer. Here’s how it compares to every alternative in the market.
| Capability | PgBouncer | pgpool-II | PgCat | Odyssey | HAProxy | AWS RDS Proxy | HeliosProxy |
|---|---|---|---|---|---|---|---|
| Connection Pooling | 3 modes | Yes | Yes | Yes | L4 only | Yes | 3 modes + AI-aware |
| Multi-threaded | (Rust) | (C99) | (C) | N/A | (Rust) | ||
| Query Caching | Basic | 3-tier (opt-in) | |||||
| Load Balancing | + schema-aware | ||||||
| Auto Failover | Basic (health-check) | + circuit breaker | |||||
| Rate Limiting | Basic (stick-tables) | Per-tenant, per-query | |||||
| Multi-Tenancy | Full isolation (4 modes) | ||||||
| Auth Proxy | Basic | Basic | Basic | Basic | IAM only | JWT/OAuth/LDAP/SAML | |
| Query Analytics | L4/L7 stats only | CloudWatch | P50/P90/P99 + cost attr. | ||||
| GraphQL Gateway | Auto-generated | ||||||
| WASM Plugins | (sandboxed) | ||||||
| Branch-Aware | Git-like branching | ||||||
| AI/RAG Caching | Semantic + conversation | ||||||
| Query Rewriting | Tenant injection + optimization | ||||||
| Transaction Replay | In-session, no driver needed | ||||||
| Replay Verification | Response digest; 40001 on divergence | ||||||
| Session State Restore | SET, transactional + savepoint-scoped | ||||||
| Write Routing | Basic (port-based) | TWR (any-node connect) | |||||
| Sharding | Schema-aware routing | ||||||
| Vendor Lock-in | None | None | None | None | None | AWS only | None |
Two-tier cache (per-connection L1, shared in-process L2; a semantic tier is planned) with an 85% hit rate (internal tests, HeliosProxy query cache vs uncached reads; workload-dependent). Of the tools in the table above, only HeliosProxy has a multi-tier cache.
HeliosProxy's transaction and statement pooling modes let many client connections share a bounded pool of backend connections per user and database; the achievable ratio depends on the workload, so measure it on your own traffic.
Deploy anywhere — Docker, Kubernetes, bare metal. Unlike AWS RDS Proxy, HeliosProxy works with any PostgreSQL-compatible database.
Semantic query cache, RAG chunk caching, conversation context, and tool result cache. Purpose-built for AI/Agent database workloads.
Based on our review of the tools in the table above: WASM plugins, GraphQL gateway, branch-aware caching, AI workload optimization, in-session transaction replay, replay verification, session state restore, write routing, semantic caching, per-tenant analytics, query routing hints, batch coalescing, switchover buffer, transaction journal.
Replaces PgBouncer + Redis + rate limiter + auth proxy + GraphQL server + analytics. One binary, one config file, one deployment.
HeliosProxy is a programmable PostgreSQL data-plane: a wire-protocol connection router that pools connections, splits reads from writes and keeps client sessions alive through a primary failure with Transaction Replay. It is licensed Apache 2.0 and runs in front of any PostgreSQL-wire backend (documentation).
No. HeliosProxy is a standalone Apache 2.0 proxy for the PostgreSQL wire protocol. It runs in front of HeliosDB Nano, Lite or Full, or in front of stock PostgreSQL, and needs no application change beyond pointing the connection string at the proxy.
Yes. Built with its PostgreSQL topology provider, HeliosProxy finds the primary by polling pg_is_in_recovery(), so it works with replication managed by Patroni, pg_auto_failover, Stolon or repmgr, and with RDS, Aurora, Cloud SQL and Azure replicas. A Patroni mode follows Patroni's leader instead (topology providers).
It depends on tr_mode. In transaction mode the proxy replays the uncommitted transaction on the new primary and checks every response against what the client already saw; divergence rolls back with SQLSTATE 40001. A COMMIT whose outcome is unknown is never retried and returns 08007 (Transaction Replay).
SQL-level prepared statements, session temporary tables, open cursors and advisory locks are not restored, and SETs sent over the extended query protocol, as most JDBC drivers send them, are not tracked. SERIALIZABLE and REPEATABLE READ transactions are never replayed.
No. Transaction Replay ships in the default build and is switched on or off at runtime with tr_enabled; the old ha-tr Cargo feature is a deprecated no-op. Connection pooling is the only default Cargo feature; caching, rate limiting and WASM plugins are opt-in builds (feature flags).
HeliosProxy pools in session, transaction and statement modes, the same three modes PgBouncer offers. Session mode keeps a server connection for the whole client session, transaction mode returns it after each COMMIT or ROLLBACK, and statement mode returns it after each statement.
Install it from crates.io with cargo install heliosdb-proxy, which needs Rust 1.86 or newer, or pull the container image from ghcr.io/heliosdatabase/hdb-heliosdb-proxy. Configure it with a proxy.toml that lists your backend nodes; the admin API binds to loopback by default.
Yes. HeliosProxy is licensed Apache 2.0, so you can use it in commercial, managed-service and proprietary deployments without copyleft obligations. Its Kubernetes operator, Terraform provider and Pulumi provider are not publicly released.
HeliosProxy is open source under Apache 2.0 and works with all three HeliosDB editions — Nano, Lite, and Full — plus any PostgreSQL-compatible database.