---
title: "Release History"
description: "HeliosProxy changes by release, upgrade notes for each major version, and the earlier release notes."
---

# Release History

Release-by-release changes and upgrade notes for HeliosProxy. The repository
[CHANGELOG](https://github.com/HeliosDatabase/HeliosDB-Proxy/blob/main/CHANGELOG.md) is the
complete record, and [GitHub Releases](https://github.com/HeliosDatabase/HeliosDB-Proxy/releases)
carries the release binaries. The container image
`ghcr.io/heliosdatabase/hdb-heliosdb-proxy` has a tag for each release version, its
major.minor line and `latest`.

The reference pages of this documentation describe the 2.0 release line. 2.1.0 changes
several defaults: read its upgrade notes below before moving to it.

## 2.1.0

Released 2026-10-15. Read offload to standbys works as documented and is on by default. Session settings
(`SET`, `RESET`, `DISCARD ALL`, `SET ROLE`) are tracked statement by statement on both wire
protocols, so offloaded reads and Transaction Replay re-homes carry them, and a failover
that cannot restore them exactly is refused instead of continuing without them. A Patroni
leader counts only while it holds the DCS leader lock, under a lease no longer than
Patroni's own, and a session whose home stops being the leader is re-homed. Reconnect
waves, backend connections per node and client sessions per tenant can be capped; the
query cache can follow logical replication; Transaction Replay covers prepared statements
and portals from earlier cycles.

Upgrade notes (behaviour changes):

- **Reads go to standbys by default.** With `[load_balancer] read_write_split = true` (the
  default), a side-effect-free read outside a transaction runs on a standby
  (`standby_reads = "async"`); a session reads its own writes from the primary for
  `read_your_writes_ms` (1000). `standby_reads = "primary"` keeps the 2.0 routing.
  Standbys that require a password need `[auth] mode = "scram"` with an `auth_file`;
  otherwise those reads fall back to the primary.
- **A failover can refuse a session with `08006`** when the proxy cannot restore its
  settings exactly (`set_config(..., false)`, a cycle it cannot read statement by
  statement, or more distinct variables than `[limits] tr_max_session_set_statements`)
  until the session sends `DISCARD ALL`, instead of re-homing it without them.
- **Reconnects are metered:** `[limits] max_concurrent_reconnects_per_node = 16` by
  default (`0` = unlimited, the 2.0 behaviour).
- **Patroni:** `[topology] patroni_confirm_leader_lock = true` by default (the leader's own
  REST API must answer `GET /primary` with 200), and startup rejects a
  `lease_timeout_secs` that is not below `patroni_ttl_secs - patroni_loop_wait_secs`
  (defaults 30 and 10): set those to the cluster's Patroni values.
- **Admin token:** an empty or whitespace-only `admin_token` is a startup error.
  Command-line deployments can now pass `--admin-token` or explicitly opt into
  `--admin-allow-insecure`; neither flag can be combined with `--config`.
- **Shorter configuration files:** omitted sections and keys, including partial `[pool]`,
  `[health]` and `[load_balancer]` sections, take the same defaults as the command line;
  a node's `port`, `weight` and `enabled` default to 5432, 100 and `true`. Each node still
  needs `host` and `role`.
- **Gateways** (HTTP SQL, GraphQL, MCP) now apply `[rate_limit]`, `[query_rewrite]` and
  `[circuit_breaker]`.
- **Library users only:** `JournalOp` gains a `PreparedCommitted` variant and several
  public structs gain fields; see the CHANGELOG. The daemon's configuration, command line,
  wire protocol and admin API stay compatible.

## Upgrading to 2.0

HeliosProxy 2.0.0 keeps the 1.x configuration format: a 1.9 `proxy.toml` loads unchanged.
The major version marks behaviour changes you should review before rolling it out:

- **Gateways have a concurrency cap by default.** `[graphql_gateway]`, `[mcp]` and
  `[http_gateway]` admit at most `max_concurrent_requests = 64` requests at once. Beyond
  that the HTTP and GraphQL gateways answer `503` with `Retry-After`, and MCP answers a
  JSON-RPC error (`-32000`) for `tools/call`; health checks and MCP
  `initialize`/`ping`/`tools/list` are never gated. Raise the key if you run more
  concurrent gateway requests. `query_timeout_ms` (default `30000`) replaces the fixed
  30-second gateway timeout.
- **Unknown config keys are reported at any nesting depth.** A typo inside a section
  (`[cache] l1_max_byts`) now logs `WARN unknown config key 'cache.l1_max_byts' ignored`
  at startup, and fails startup when `strict_config = true`. Previously only top-level
  keys were checked, so check your startup log after upgrading.
- **Conflicting primaries fail closed** with `[topology] provider = "postgres"`. When
  several nodes are writable, the node on the strictly highest timeline wins; a tie or an
  unreadable timeline authorizes nothing (1.9 took the first writable node probed). The
  probe role needs permission to call `pg_control_checkpoint()`. See
  [Topology Providers](/docs/proxy/topology-providers/#conflicting-primaries-postgres-provider).
- **Query cache (only if you enabled it).** Writes on the extended protocol now
  invalidate it, a stale entry is refused on every tier (L1 and L3 used to be served
  until TTL), and DDL, `TRUNCATE`, `COPY ... FROM`, `EXECUTE`, `CALL` and `DO` invalidate
  the whole cache. Expect a lower hit rate on write-heavy workloads in exchange for
  read-your-commits correctness. The transaction-journal capture now also runs when
  `tr_enabled = false` but the cache is on. The cache stays **off by default**; see
  [why](/docs/proxy/configuration/#query-cache-cache).
- **Library users only:** the `TopologyProvider` trait gains defaulted
  `conflicts_total()` and `leader_timeline()` methods (existing implementations keep
  compiling), and `QueryCache::purge_tables` no longer removes L2 entries itself.

New in 2.0 that you may want to turn on: `[topology] provider = "patroni"`
([Topology Providers](/docs/proxy/topology-providers/#patroni-provider-postgres-topology-provider--patroni)),
and the Prometheus counters `heliosdb_proxy_topology_conflicting_primaries_total`,
`heliosdb_proxy_backend_capacity_waits_total` and
`heliosdb_proxy_backend_capacity_refusals_total`.

Coming from 1.7 or earlier, also note the 1.8 change (`ha-tr` is a no-op; Transaction
Replay is always compiled and `tr_enabled` is the runtime switch) and that 1.9 added the
`[journal]`, `[topology]`, `strict_config` and `[limits]` keys described in
[Configuration](/docs/proxy/configuration/) — all default to the previous behaviour.

## Highlights by release

Highlights from 0.5.0 to 2.0.0. The repository [CHANGELOG](https://github.com/HeliosDatabase/HeliosDB-Proxy/blob/main/CHANGELOG.md) has the complete history.

- **2.0.0** (2026-09-25) — The HA topology, the query cache and Transaction Replay share one model of what the backend actually committed. The query cache (still opt-in) invalidates on commit on both wire protocols and every tier, with DDL, `TRUNCATE`, `COPY ... FROM`, `EXECUTE`, `CALL` and `DO` invalidating the whole cache; a Patroni cluster can be the write authority (`[topology] provider = "patroni"`); conflicting primaries under the `postgres` provider are resolved by the strictly highest timeline or fail closed; gateways gain `query_timeout_ms` and `max_concurrent_requests`; unknown config keys are reported at any nesting depth; a login burst against a backend at `max_connections` no longer surfaces as a false authentication failure; `--tr false` works. Read the [upgrade notes](#upgrading-to-20) and the [announcement](https://www.heliosdb.com/blog/heliosproxy-2-0-0-committed-history-patroni-failover.html).
- **1.9.0** (2026-09-22) — Recovery-grade transaction journal: real committed transactions with parameters and outcomes, an optional durable on-disk journal (`[journal] dir`, CRC-checked segments, torn-tail truncation, `commit`/`interval`/`none` fsync), and `POST /api/replay` `mode: "committed_history"`. Authoritative topology (`[topology] provider = "postgres"`) with an authority lease (`lease_timeout_secs`); `GET /capabilities` and opt-in `strict_config`; `[load_balancer] read_strategy` honoured (new `power_of_two`); credentialed health probes and measured replica lag (`require_known_lag`); bounded fair client admission (`client_admission_wait_secs`); pooled gateway backend connections (`gateway_pool_max_idle`); byte budgets for the L1/L3 and edge caches; `replay_deadline_secs`; rustls 0.23.45 (RUSTSEC-2026-0285).
- **1.8.0** (2026-09-12) — Transaction Replay is part of the default build; the `ha-tr` cargo feature is a deprecated no-op and `tr_enabled` is the runtime switch (`false` stops journaling, forces `tr_mode = "none"`, and makes `POST /api/replay` return `503`). Dependency security updates (`reqwest` 0.12, `wasmtime` 36, `lru` 0.18); the unused `prometheus`/`opentelemetry` dependencies were dropped. `GET /api/migration/status` no longer reports `migration_ready` while applies are failing.
- **1.7.0** — Completes the Transaction Replay series: replay verifies each statement's response digest against what the client already saw (divergence rolls back with `40001`), `SERIALIZABLE`/`REPEATABLE READ` transactions are never replayed, an interrupted read is only re-executed when every function it calls is provably side-effect-free (built-in allowlist plus the new `tr_read_functions`), session `SET` restore is transactional and savepoint-scoped, exceeding `tr_max_session_set_statements` refuses the failover with `08006` rather than re-homing with partial state, and `write_timeout_secs` is now one deadline for the entire recovery. New `[limits]` bounds: `tr_max_observation_bytes`, `backend_response_timeout_secs`, `max_backend_frame_bytes`.
- **1.6.1** — Transaction Replay commit-outcome and delivery safety: a possibly-committed statement is never re-executed (`08007` asks the client to verify), recovery never appends a second result to a response the client already partly received, the idle backend-watch relay forwards only complete frames, and `SET`s from a rolled-back transaction are no longer restored.
- **1.6.0** — `tr_mode` now drives real in-session failover on both query protocols; backend faults return a proper PostgreSQL `ErrorResponse` instead of a dropped socket; SCRAM/MD5/cleartext backend authentication on redial; new `[limits]` and `[cache]` bounds; per-query hot-path performance work.
- **1.5.0** — `[limits]` and `[anomaly]` configuration sections; `/admin/kv/<plugin>/<key>` endpoints for pushing plugin runtime config; `/healthz`, `/livez`, `/readyz` probe routes; admin dashboard fixed to work with `admin_token` set. **Contains a stored-XSS fix for the 1.4.0 admin dashboard — 1.4.0 operators should upgrade.**
- **1.4.0** — Admin API binds loopback by default (breaking); environment-variable substitution in config files; edge/geo result-cache mode; MCP bearer auth; gateway and admin request hardening.
- **1.3.0 / 1.3.1** — In-band failure detection, protocol-level health probes, `/api/circuit`, idle-connection reaper.
- **1.2.0** — Real LDAP search-then-bind authentication (`ldap-auth`).
- **1.1.0** — Transaction and statement pooling do real work on the data path.
- **1.0.0** — First stable release; every feature flag does real work, and the limits of each capability are documented.
- **0.5.0** — Client TLS/mTLS, proxy-terminated SCRAM-SHA-256, pg_hba-style admission rules, MCP agent gateway, HTTP SQL gateway, admin bearer auth, SIGHUP reload and SIGUSR2 binary handoff.

### Transaction Replay

- **1.6.0** (2026-09-04) — introduced `tr_mode` in-session failover.
- **1.6.1** (2026-09-09) — fixed commit-outcome, publication and delivery safety.
- **1.7.0** (2026-09-11) — completes the series: verification, refusals, and one
  deadline.
- **1.8.0** (2026-09-12) — Transaction Replay is part of the default build; `ha-tr`
  becomes a deprecated no-op and `tr_enabled` the runtime switch.
- **1.9.0** (2026-09-22) — recovery-grade journal: real committed transactions with
  parameters and outcomes, optional durable segments (`[journal]`), and
  `POST /api/replay` `mode: "committed_history"`; write-path journaling no longer
  convoys concurrent writers. Before 1.9.0 the journal held post-response statement text
  only, as synthetic one-statement transactions, and extended-protocol writes were not
  journaled.
- **2.0.0** (2026-09-25) — the journal capture also drives commit-aware query-cache
  invalidation (and runs whenever the cache is on); `--tr false` / `--tr=false` now
  actually turn Transaction Replay off.

## Release notes

- [0.4.0: From Connection Router to Programmable Data-Plane](/docs/proxy/releases/release-notes-v040/)
- [0.3.1: Hot-path Performance & Correctness](/docs/proxy/releases/release-notes-v031/)
