1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# =============================================================================
# HeliosProxy - PostgreSQL Cluster Configuration
# =============================================================================
#
# Pure PostgreSQL deployment: 3-node streaming replication cluster with
# read/write splitting, transaction pooling, and health checks.
#
# Topology:
# pg-primary — accepts all writes and can serve reads
# pg-sync — synchronous standby (zero-lag, promotable)
# pg-async — asynchronous standby (some lag, read-only overflow)
#
# No HeliosDB-specific features are enabled (no cache, no semantic layer,
# no GraphQL gateway, no WASM plugins, no branch routing).
#
# This configuration is suitable for direct comparison with PgBouncer or
# pgpool-II in a standard PostgreSQL environment.
# =============================================================================
# PROXY — Listener addresses
# =============================================================================
= "${HELIOS_PROXY_LISTEN:-0.0.0.0:6432}"
= "${HELIOS_PROXY_ADMIN:-0.0.0.0:9090}"
# Transaction Replay is disabled — standard PostgreSQL does not expose the
# WAL metadata needed for automatic replay. Handle retries in the application.
= false
= "none"
# Time to wait for a new primary during manual/orchestrated failover.
= 30
# =============================================================================
# POOL — Backend connection pool
# =============================================================================
[]
# Size according to: (number of vCPUs * 2) + max_parallel_workers on the
# PostgreSQL side, then subtract connections reserved for superuser and
# replication. A safe default for most workloads:
= 10
= 100
= 300
= 1800
= 5
# Always verify a connection is alive before handing it to a client.
= true
# =============================================================================
# POOL MODE — Transaction pooling
# =============================================================================
[]
# Transaction mode gives the best connection reuse for web applications.
# Each client gets a backend connection only for the duration of a transaction.
= "transaction"
= 100
= 10
= 300
= 1800
= 5
# DISCARD ALL resets all session state (SET variables, prepared statements,
# temp tables) when a connection is returned to the pool.
= "DISCARD ALL"
# Track prepared statements so the proxy can re-create them transparently
# when a client's queries land on a different backend connection.
= "track"
# Lightweight check on every acquire.
= "SELECT 1"
# =============================================================================
# LOAD BALANCER — Read/write splitting
# =============================================================================
[]
# Distribute reads across healthy standbys using round-robin.
= "round_robin"
# Route SELECT queries to standbys; INSERT/UPDATE/DELETE/DDL to primary.
= true
# If a standby's average latency exceeds this threshold (ms), stop routing
# reads to it until latency recovers.
= 100
# =============================================================================
# HEALTH — PostgreSQL health checks
# =============================================================================
[]
# Probe every node every 5 seconds.
= 5
# A health check probe that takes longer than this is considered failed.
= 3
# After 3 consecutive failures a node is marked unhealthy and removed from
# the routing pool.
= 3
# After 2 consecutive successes a recovered node is added back.
= 2
# SELECT 1 is the fastest possible check. For deeper validation you could
# use: "SELECT CASE WHEN pg_is_in_recovery() THEN 1 ELSE 1 END"
= "SELECT 1"
# =============================================================================
# NODES — 3-node PostgreSQL cluster
# =============================================================================
# ---------- Primary ----------
# The single read-write node. All writes and, when read_write_split is
# disabled, all reads go here.
[[]]
= "${PG_PRIMARY_HOST:-pg-primary}"
= ${PG_PRIMARY_PORT:-5432}
= "primary"
= 100
= true
= "pg-primary"
# ---------- Synchronous Standby ----------
# Configured with synchronous_commit = on in postgresql.conf.
# Zero data loss — every commit is confirmed replicated here before the
# client receives OK. Safe for strong-consistency reads.
[[]]
= "${PG_SYNC_HOST:-pg-sync}"
= ${PG_SYNC_PORT:-5432}
= "standby"
= 100
= true
= "pg-sync"
# ---------- Asynchronous Standby ----------
# Best-effort replication. May lag behind the primary by a few transactions.
# Good for read-heavy workloads that tolerate eventual consistency. Given a
# lower weight so the synchronous standby is preferred for reads.
[[]]
= "${PG_ASYNC_HOST:-pg-async}"
= ${PG_ASYNC_PORT:-5432}
= "standby"
= 50
= true
= "pg-async"
# =============================================================================
# CACHE — Disabled (no HeliosDB features)
# =============================================================================
[]
= false
# =============================================================================
# HA — High availability
# =============================================================================
[]
= true
# Automatically promote the synchronous standby if the primary becomes
# unreachable. Requires an external promotion mechanism (e.g., Patroni,
# pg_auto_failover, or a custom script invoked via webhook).
= true
= 3
# Only route reads to standbys within this replication lag (milliseconds).
# The synchronous standby will always be within this limit. The async
# standby will be excluded when it falls behind.
= 100
# =============================================================================
# LOGGING
# =============================================================================
[]
= "${HELIOS_PROXY_LOG_LEVEL:-info}"
= "pretty"
# =============================================================================
# METRICS — Prometheus
# =============================================================================
[]
= true
= "0.0.0.0:9100"