Overview
TimescaleDB Highly Available deploys the TimescaleDB time-series database (a PostgreSQL 18 extension) as a Patroni-managed cluster with automatic failover. Three replicas — one leader plus two hot standbys — form the cluster over an etcd consensus store, and an HAProxy leader endpoint routes all writes to the current primary. When the leader fails, Patroni promotes a standby and HAProxy re-selects the new primary automatically, giving applications a single stable endpoint. Optional PgBouncer connection pooling and scheduled logical backups to AWS S3, GCS, or MinIO are included.TimescaleDB is licensed under the Timescale License (TSL) plus the PostgreSQL License. It is free to self-host at any scale, including all Community features (compression, continuous aggregates, retention); the license only forbids reselling TimescaleDB itself as a managed database service.
For high availability, keep at least 3 TimescaleDB replicas and 3 etcd replicas. etcd requires an odd number of replicas (3, 5, 7) for quorum.
replicas: 1 renders a single-member cluster with no failover.What Gets Created
- Stateful TimescaleDB Workload — A Patroni-managed PostgreSQL 18 + TimescaleDB 2.28.3 cluster on port
5432(replicas: 3by default: 1 leader + 2 hot standbys). Each replica has per-replica DNS and its own volume; the extension is preloaded and created automatically in your database. Leadership is handed off before any replica is shut down, keeping writes available during deployments and restarts. - etcd Workload — A dedicated etcd cluster providing the distributed consensus store (DCS) for Patroni leader election, from the
etcdsubchart dependency. - HAProxy Leader-Routing Workload (enabled by default) — Routes write traffic to the current primary via Patroni’s REST health check, providing a stable connection endpoint across failover.
- PgBouncer Workload (optional) — A connection pooler deployed in front of HAProxy, multiplexing application connections into a smaller pool of real database connections.
- Backup Cron Workload (optional) — A scheduled
pg_dumpalllogical backup that dumps the leader through HAProxy and writes a compressed SQL dump to AWS S3, GCS, or MinIO. - Volume Sets — Per-replica persistent storage for the TimescaleDB and etcd data directories, with optional autoscaling.
- Secrets — A dictionary secret with database credentials, plus opaque secrets for the Patroni and HAProxy start scripts.
- Identity & Policy — An identity bound to the workload with least-privilege
revealaccess to exactly those secrets, and scoped cloud storage access when backup is enabled.
This template does not create a GVC. You must deploy it into an existing GVC.
Installation
This template has no external prerequisites unless backup is enabled. To install, follow the instructions for your preferred method:UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Configuration
The defaultvalues.yaml for this template:
Credentials
postgres.username— Database superuser username. Change before deploying to production.postgres.password— Database superuser password. Change before deploying to production.postgres.database— Name of the database created on first startup. The TimescaleDB extension is created automatically inside it.
These values are only applied on first startup when the data directory is empty. Updating them after the initial deployment has no effect on the running database. To change credentials or the database name on an existing cluster, use PostgreSQL’s native commands (e.g.
ALTER USER, ALTER DATABASE).Cluster and Resources
replicas— Number of TimescaleDB replicas (default3: 1 leader + 2 hot standbys). Use at least 3 for high availability.image— The TimescaleDB HA image tag (PostgreSQL 18 + TimescaleDB 2.28.3 Community, with Patroni bundled).resources.minCpu/resources.minMemory— Minimum CPU and memory guaranteed per replica.resources.maxCpu/resources.maxMemory— Maximum CPU and memory per replica.multiZone— Spread replicas across availability zones within the location.
Storage
volumeset.capacity— Initial volume size in GiB (minimum 10). Each replica gets its own volume.volumeset.autoscaling.enabled— Automatically expand the volume as it fills. When enabled:maxCapacity— Maximum volume size in GiB.minFreePercentage— Trigger a scale-up when free space drops below this percentage.scalingFactor— Multiply the current capacity by this factor when scaling up.
etcd Cluster
etcd.replicas— Number of etcd replicas. Must be an odd number (3, 5, 7) for quorum.etcd.resources.cpu/etcd.resources.memory— CPU and memory per etcd replica.etcd.multiZone— Spread etcd replicas across availability zones.etcd.volumeset.capacity— Initial volume size for etcd data in GiB.etcd.internal_access.type— Controls which workloads can reach the etcd cluster.
etcd is a hard dependency. If the etcd members are unhealthy, Patroni loses its consensus store and the cluster goes read-only. If writes start failing, check the
RELEASE_NAME-etcd workload first.HAProxy Leader Endpoint
In a Patroni cluster, only the leader replica accepts writes — the standbys are read-only. HAProxy automatically routes writes to the current leader by health-checking each replica’s Patroni REST endpoint, giving applications a stable connection endpoint even during failover. It is enabled by default.proxy.enabled— Deploy the HAProxy leader-routing workload (default:true).proxy.resources.cpu/proxy.resources.memory— CPU and memory per HAProxy replica.proxy.minReplicas/proxy.maxReplicas— Replica count for the proxy workload.
proxy.enabled must stay true for logical backups — the backup job dumps the leader through the proxy endpoint.Internal Access
The cluster is internal-only; there is no public endpoint. Reach it from other workloads through the proxy (or PgBouncer).internal_access.type— Controls which workloads can connect to the cluster on port5432:
internal_access.workloads— Whentypeisworkload-list, the list of workload links (e.g.//gvc/GVC_NAME/workload/WORKLOAD_NAME) allowed to connect.
PgBouncer Connection Pooling
PgBouncer is an optional connection pooler that sits in front of HAProxy, multiplexing application connections into a smaller pool of real database connections. HAProxy handles leader routing and failover transparently — PgBouncer is unaware of which replica is the primary. Enabling PgBouncer automatically enables HAProxy, as it is required for leader-aware routing. When enabled, PgBouncer becomes the primary connection endpoint:pgbouncer.poolMode— Controls how connections are reused:
pgbouncer.defaultPoolSize— Number of real database connections PgBouncer maintains per pod (default:25).pgbouncer.maxClientConn— Maximum number of client connections PgBouncer accepts per pod (default:1000).pgbouncer.maxDbConnections— Hard cap on total PostgreSQL connections across all PgBouncer pods (default:100). Prevents connection blowout when PgBouncer scales out.pgbouncer.minReplicas/pgbouncer.maxReplicas— PgBouncer autoscales between these bounds.pgbouncer.resources.cpu/pgbouncer.resources.memory— Resources allocated to each PgBouncer pod.
Backup
Backup is disabled by default. When enabled, a cron workload runspg_dumpall against the leader (through HAProxy) on the configured schedule and uploads a compressed SQL dump to AWS S3, GCS, or a MinIO-compatible endpoint.
backup.enabled— Enable scheduled logical backups.backup.image— The backup container image. Match its tag to the server major version —18.1.0for the default PostgreSQL 18 image.backup.schedule— Cron expression for backup frequency (default: daily at 2am UTC).backup.provider—aws,gcp, orminio.backup.resources.cpu/backup.resources.memory— Resources for the backup cron container.
Connecting
Always connect through the proxy (or PgBouncer) — never a raw replica address, since the leader moves on failover.Using TimescaleDB
Any PostgreSQL client or ORM works unchanged. Turn a regular table into a hypertable (automatically partitioned by time) and query it with time buckets:Availability During Failover and Upgrades
The cluster keeps writes available across leader changes, but applications should implement connection retry with exponential backoff — a few seconds of write interruption is expected at each leader restart:- Automatic failover — When the leader fails, Patroni promotes a standby (a manual/orchestrated promotion completes in roughly 5 seconds in testing, with no committed rows lost) and HAProxy re-selects the new primary automatically, with no client change.
- Rolling restarts and upgrades — Each replica is restarted in turn; leadership is handed off before the leader shuts down. Expect a brief write gap (a few seconds) at each leader switchover during the roll.
Backup Prerequisites
AWS S3
Before enabling backup withprovider: aws, complete the following in your AWS account:
1
Create a bucket
Create an S3 bucket. Set
backup.aws.bucket to its name and backup.aws.region to its region.2
Set up a Cloud Account
If you do not have one, create a Cloud Account for your AWS account. Set
backup.aws.cloudAccountName to its name.3
Create an IAM policy
Create an IAM policy with the JSON below, replacing
YOUR_BUCKET_NAME, then set backup.aws.policyName to the policy’s name and backup.aws.prefix to the folder path for backups.GCS
Before enabling backup withprovider: gcp, complete the following in your GCP account:
1
Create a bucket
Create a GCS bucket. Set
backup.gcp.bucket to its name.2
Set up a Cloud Account
If you do not have one, create a Cloud Account for your GCP project. Set
backup.gcp.cloudAccountName to its name — access is keyless, with no stored credentials.MinIO
Before enabling backup withprovider: minio, ensure your MinIO instance (or any S3-compatible endpoint) is accessible:
1
Create a bucket
Create a bucket on the server. Set
backup.minio.bucket to its name.2
Set the endpoint
Set
backup.minio.endpoint to the S3 API address including the port. For the minio marketplace template deployed in the same GVC, use http://WORKLOAD_NAME:9000.3
Set credentials
Set
backup.minio.accessKey and backup.minio.secretKey to credentials with access to the bucket. For the MinIO template, these match the admin.username and admin.password values. Set backup.minio.prefix to the folder path for backups.MinIO backup requires no Control Plane Cloud Account — credentials are passed directly to the backup job.
Restoring a Backup
Restoring a TimescaleDB dump is not the vanilla PostgreSQL procedure. The target server must run the same TimescaleDB extension version as the dump, and the replay must be wrapped intimescaledb_pre_restore() and timescaledb_post_restore(). Connect through the proxy so the restore targets the current leader.
AWS S3:
gsutil cp "gs://BUCKET_NAME/PREFIX/BACKUP_FILE.sql.gz" -. For MinIO, add --endpoint-url "http://MINIO_ENDPOINT:9000" to the aws s3 cp command and export the MinIO access and secret keys as AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
Important Notes
- Change
postgres.passwordbefore installing. Credentials are baked into the data directory at first boot; changing the value later does not change the database password. To reset, uninstall (which deletes the volumes) and reinstall. - Always connect via the proxy, never a replica. The leader moves on failover; a pinned replica address will break. PgBouncer and backups already route through the proxy.
replicas: 1has no HA. It renders a single-member Patroni cluster with no failover. Use at least 3, and an oddetcd.replicas(3, 5, 7) for quorum.- etcd is a hard dependency. If the etcd members are unhealthy, Patroni loses its consensus store and the cluster goes read-only — check
RELEASE_NAME-etcdfirst if writes fail. proxy.enabledmust staytruefor backups. The logical backup dumps the leader through the proxy endpoint.- Backups are logical-only. A scheduled
pg_dumpall; continuous WAL archiving / point-in-time restore is a planned follow-up. - Expect a brief write interruption per leader restart. During failover or a rolling upgrade, applications should retry with exponential backoff.
External References
TimescaleDB Documentation
Official TimescaleDB documentation
Hypertables
Hypertables, compression, continuous aggregates, and retention
Patroni Documentation
Patroni automatic failover documentation
etcd Documentation
Official etcd documentation
Restoring a TimescaleDB Backup
Using timescaledb_pre_restore and timescaledb_post_restore
TimescaleDB HA Template
View the source files, default values, and chart definition