---
title: "HeliosProxy Configuration Reference"
description: "The core proxy.toml settings for running HeliosProxy in front of HeliosDB Lite, with defaults and a complete example."
---

# HeliosProxy Configuration Reference

This page covers the `proxy.toml` settings you need to run HeliosProxy in front of HeliosDB Lite. The [HeliosProxy configuration reference](/docs/proxy/configuration/) documents every key, including the optional sections for caching, routing hints, rate limiting, multi-tenancy, plugins and the gateways.

---

## Configuration File Format

HeliosProxy reads a TOML file:

```bash
heliosdb-proxy --config /path/to/config.toml
```

When `--config` is given, the file drives the whole configuration. HeliosProxy warns about unknown keys and ignores them. Set `strict_config = true` to make an unknown key, or a subsystem this build cannot deliver, a startup error.

---

## Top-Level Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `listen_address` | string | `"0.0.0.0:5432"` | Address for client connections. Required in a config file. |
| `admin_address` | string | `"127.0.0.1:9090"` | Address for the admin API. Loopback by default. Required in a config file. |
| `admin_token` | string | *(none)* | Bearer token for the admin API. Required when `admin_address` is not a loopback address. |
| `admin_allow_insecure` | bool | `false` | Explicit opt-in to a non-loopback admin bind without a token. Use it only behind your own authenticating proxy or network policy. |
| `strict_config` | bool | `false` | Fail at startup on unknown keys or on subsystems this build cannot deliver. |
| `tr_enabled` | bool | `true` | Transaction Replay master switch. Required in a config file. |
| `tr_mode` | string | `"session"` | Transaction Replay mode (see below). Required in a config file. |
| `write_timeout_secs` | u64 | `30` | One deadline for a whole session recovery: waiting for a primary, reconnecting, restoring session state and replaying. |

If `admin_address` is a non-loopback address, `admin_token` is unset and `admin_allow_insecure` is `false`, the proxy refuses to start. To fix it, set `admin_token`, bind the admin API to `127.0.0.1`, or set `admin_allow_insecure = true` only when another layer authenticates admin requests.

### Transaction Replay Modes (`tr_mode`)

| Mode | Behaviour when the backend fails mid-request |
|------|-------------|
| `none` | The client receives one error and the connection is closed. |
| `session` | The session stays open. Session settings are restored, and a statement that never reached the backend (outside a transaction) is re-run. |
| `select` | `session`, plus side-effect-free reads are re-run. |
| `transaction` | `select`, plus an uncommitted explicit transaction is replayed and verified on the new primary. |

A `COMMIT` whose outcome is unknown is never retried in any mode. See [Transaction Replay](/docs/proxy/transaction-replay/) for the exact rules.

---

## Pool Mode Configuration (`[pool_mode]`)

Optional. Controls when backend connections return to the pool.

> **HeliosDB Lite backends:** use session pooling (the default). Transaction and statement pooling reset each connection with `DISCARD ALL` when it returns to the pool, and `DISCARD ALL` is planned for Lite; until then the reset fails, HeliosProxy closes the backend connection instead of reusing it, and pooling gives no benefit.

```toml
[pool_mode]
mode = "session"
max_pool_size = 100
min_idle = 10
idle_timeout_secs = 600
max_lifetime_secs = 3600
acquire_timeout_secs = 5
reset_query = "DISCARD ALL"
prepared_statement_mode = "track"
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `mode` | string | `"session"` | Pooling mode: `session`, `transaction`, `statement` |
| `max_pool_size` | u32 | `100` | Maximum backend connections per node |
| `min_idle` | u32 | `10` | Minimum idle connections |
| `idle_timeout_secs` | u64 | `600` | Idle connection timeout |
| `max_lifetime_secs` | u64 | `3600` | Maximum connection lifetime |
| `acquire_timeout_secs` | u64 | `5` | Connection acquire timeout |
| `reset_query` | string | `"DISCARD ALL"` | SQL run when a connection returns to the pool |
| `prepared_statement_mode` | string | `"disable"` | Prepared statement handling: `disable`, `track`, `named` |

### Pooling Modes

| Mode | Connection Returns | Best For |
|------|-------------------|----------|
| `session` | On client disconnect | Legacy apps, prepared statements |
| `transaction` | After COMMIT/ROLLBACK | Web apps, microservices (with Lite, once `DISCARD ALL` is available) |
| `statement` | After each statement | Simple queries, high concurrency (with Lite, once `DISCARD ALL` is available) |

### Prepared Statement Modes

| Mode | Behavior |
|------|----------|
| `disable` | Not tracked (safest for transaction and statement pooling) |
| `track` | Track PREPARE/DEALLOCATE and recreate on a new connection |
| `named` | Protocol-level named statements |

---

## Connection Pool Configuration (`[pool]`)

Required section. Every key must be present.

```toml
[pool]
min_connections = 2
max_connections = 100
idle_timeout_secs = 300
max_lifetime_secs = 1800
acquire_timeout_secs = 30
test_on_acquire = true
```

| Option | Type | Typical value | Description |
|--------|------|---------|-------------|
| `min_connections` | usize | `2` | Minimum connections per node |
| `max_connections` | usize | `100` | Maximum connections per node (must be >= `min_connections`) |
| `idle_timeout_secs` | u64 | `300` | Idle connection timeout |
| `max_lifetime_secs` | u64 | `1800` | Maximum connection lifetime |
| `acquire_timeout_secs` | u64 | `30` | Connection acquire timeout |
| `test_on_acquire` | bool | `true` | Health-check a connection before handing it out |

---

## Load Balancer Configuration (`[load_balancer]`)

Required section.

```toml
[load_balancer]
read_strategy = "round_robin"
read_write_split = true
latency_threshold_ms = 100
```

| Option | Type | Typical value | Description |
|--------|------|---------|-------------|
| `read_strategy` | string | `"round_robin"` | Read routing strategy |
| `read_write_split` | bool | `true` | Route writes to the primary and reads to standbys and replicas |
| `latency_threshold_ms` | u64 | `100` | Latency above which a node is treated as unhealthy for routing |

### Routing Strategies (`read_strategy`)

| Strategy | Description |
|----------|-------------|
| `round_robin` | Rotate through nodes equally |
| `weighted_round_robin` | Rotate in proportion to each node's `weight` |
| `least_connections` | Route to the node with the fewest attached sessions |
| `latency_based` | Route to the node with the lowest measured probe latency |
| `random` | Random node selection |
| `power_of_two` | Sample two nodes and pick the one with fewer attached sessions |

---

## Health Check Configuration (`[health]`)

Required section.

```toml
[health]
check_interval_secs = 5
check_timeout_secs = 3
failure_threshold = 3
success_threshold = 2
check_query = "SELECT 1"
```

| Option | Type | Typical value | Description |
|--------|------|---------|-------------|
| `check_interval_secs` | u64 | `5` | Interval between probes (must be at least 1) |
| `check_timeout_secs` | u64 | `3` | Probe timeout |
| `failure_threshold` | u32 | `3` | Consecutive failures before a node is marked unhealthy |
| `success_threshold` | u32 | `2` | Consecutive successes before it is healthy again |
| `check_query` | string | `"SELECT 1"` | Query used when `user` is set |
| `user` / `password` / `database` | string | *(none)* | Optional probe credentials. Without them the probe is a credential-less protocol check. |

---

## Node Configuration (`[[nodes]]`)

One entry per backend. At least one node with `role = "primary"` is required.

```toml
[[nodes]]
host = "primary.example.com"
port = 5432
role = "primary"
weight = 100
enabled = true
name = "primary-1"

[[nodes]]
host = "standby-1.example.com"
port = 5432
role = "standby"
weight = 50
enabled = true

[[nodes]]
host = "replica-1.example.com"
port = 5432
role = "replica"
weight = 25
enabled = true
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `host` | string | required | Node hostname or IP |
| `port` | u16 | required | PostgreSQL wire port |
| `role` | string | required | `primary`, `standby` or `replica` |
| `weight` | u32 | required | Load-balancing weight |
| `enabled` | bool | required | Whether the node is routable. Toggle it at runtime with the admin API. |
| `http_port` | u16 | `8080` | HTTP API port on the backend node |
| `name` | string | optional | Human-readable name for logs and metrics |

### Node Roles

| Role | Description |
|------|-------------|
| `primary` | Read/write node (at least one required) |
| `standby` | Promotable standby. Receives reads when `read_write_split` is on. |
| `replica` | Read-only replica. Not promotable. |

HeliosProxy does not promote standbys. An external HA manager performs the promotion. With HeliosDB Lite backends, use the default static topology (configured roles plus health checks).

---

## TLS Configuration (`[tls]`)

Optional TLS for client connections. Omit the whole section to disable TLS. When the section is present, `enabled`, `cert_path`, `key_path` and `require_client_cert` must all be set.

```toml
[tls]
enabled = true
cert_path = "/path/to/cert.pem"
key_path = "/path/to/key.pem"
ca_path = "/path/to/ca.pem"
require_client_cert = false
```

| Option | Type | Description |
|--------|------|-------------|
| `enabled` | bool | Enable TLS for client connections |
| `cert_path` | string | Server certificate path (PEM) |
| `key_path` | string | Server private key path (PEM) |
| `ca_path` | string | Optional CA certificate for client-certificate verification |
| `require_client_cert` | bool | Require a valid client certificate |

---

## Complete Example

```toml
# HeliosProxy in front of a HeliosDB Lite primary, standby and replica

listen_address = "0.0.0.0:5433"
admin_address = "127.0.0.1:9090"
tr_enabled = true
tr_mode = "session"
write_timeout_secs = 30

# Connection pooling mode
[pool_mode]
mode = "session"
max_pool_size = 100
min_idle = 10

# Basic pool settings
[pool]
min_connections = 5
max_connections = 100
idle_timeout_secs = 300
max_lifetime_secs = 1800
acquire_timeout_secs = 30
test_on_acquire = true

# Load balancing
[load_balancer]
read_strategy = "least_connections"
read_write_split = true
latency_threshold_ms = 50

# Health checks
[health]
check_interval_secs = 5
check_timeout_secs = 3
failure_threshold = 3
success_threshold = 2
check_query = "SELECT 1"

# Primary node
[[nodes]]
host = "db-primary.internal"
port = 5432
role = "primary"
weight = 100
enabled = true
name = "primary"

# Standby node
[[nodes]]
host = "db-standby-1.internal"
port = 5432
role = "standby"
weight = 100
enabled = true
name = "standby-1"

# Read replica
[[nodes]]
host = "db-replica-1.internal"
port = 5432
role = "replica"
weight = 50
enabled = true
name = "replica-1"

# TLS (optional): add a complete [tls] section to enable it
# [tls]
# enabled = true
# cert_path = "/etc/heliosproxy/server.crt"
# key_path = "/etc/heliosproxy/server.key"
# require_client_cert = false
```

---

## Environment Variable Substitution

HeliosProxy has no `HELIOS_PROXY_*` override system. Instead, before parsing, it expands `${NAME}` and `${NAME:-default}` references in the file text:

```toml
listen_address = "${HELIOS_LISTEN:-0.0.0.0:5433}"
admin_token    = "${ADMIN_TOKEN}"     # startup fails if ADMIN_TOKEN is unset
```

A `${NAME}` with no default and no value in the environment stops startup with an error that names the variable. The only environment variable the proxy reads directly is `HELIOS_DRAIN_TIMEOUT_SECS`, which overrides the `SIGUSR2` drain timeout.

---

## Configuration Validation

The proxy validates the configuration on startup and refuses to start with a descriptive error when, for example:

1. A required key or section is missing, or no `[[nodes]]` entry has `role = "primary"`
2. `max_connections` is lower than `min_connections`
3. `[health] check_interval_secs` is `0`
4. `admin_address` is not loopback and neither `admin_token` nor `admin_allow_insecure = true` is set

---

## Admin API Endpoints

The admin API listens on `admin_address`. When `admin_token` is set, send `Authorization: Bearer <token>` on every route except the liveness and readiness probes.

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health`, `/healthz` | GET | Liveness |
| `/readyz` | GET | Readiness: 200 when at least one backend is healthy |
| `/nodes` | GET | Backend nodes with health |
| `/nodes/{addr}/disable` | POST | Remove a node (`host:port`) from routing |
| `/nodes/{addr}/enable` | POST | Return a node to routing |
| `/pools` | GET | Per-node connection pool statistics |
| `/config` | GET | Current configuration (read only; reload with `SIGHUP`) |
| `/metrics` | GET | Server metrics (JSON) |
| `/metrics/prometheus` | GET | Prometheus exposition text, wrapped in a JSON `text` field |

```bash
# Take a node out of routing before maintenance, then return it
curl -X POST http://127.0.0.1:9090/nodes/db-replica-1.internal:5432/disable
curl -X POST http://127.0.0.1:9090/nodes/db-replica-1.internal:5432/enable
```

The [Admin API reference](/docs/proxy/admin-api/) lists every route and response.

---

## See Also

- [HeliosProxy configuration reference](/docs/proxy/configuration/)
- [HeliosProxy feature flags](/docs/proxy/feature-flags/)
- [HeliosProxy integration guide](https://www.heliosdb.com/docs/lite/guides/heliosproxy_integration_guide/)
- [Release Notes](https://www.heliosdb.com/docs/lite/releases/heliosproxy_v100_release_notes/)
