Overview
TimescaleDB is a time-series database built as a PostgreSQL extension: hypertables that partition by time automatically, columnar compression, continuous aggregates and retention policies, all alongside ordinary relational tables and reachable from any PostgreSQL client or ORM. This template deploys one PostgreSQL 18 server with the TimescaleDB Community extension preloaded and created in your database, on a persistent volume, with an optional PgBouncer connection pooler in front of it and an optional cron job that writes compressedpg_dumpall backups to AWS S3, Google Cloud Storage or a MinIO (S3-compatible) bucket.
Database credentials are not template values. The server reads its username, password and database name from a dictionary secret you create before installing, so no password passes through Helm or lands in the release. The template creates no credential secret of its own.
What Gets Created
Prerequisites
One secret must exist before you install. It holds the credentials your applications put in their connection strings. Secrets are org-level, so no GVC flag is involved.Create the database credentials secret
username, password and database. The server creates that role (as a superuser) and that database the first time the volume is initialized, and creates the TimescaleDB extension inside that database:config.credentialsSecretName to this name. Read it back later with cpln secret reveal SECRET_NAME -o yaml — a bare cpln secret reveal prints only a summary table, not the values.Installation
Install the chart from the marketplace registry, pointing it at the secret you created:UI
CLI
Terraform
Pulumi
Configuration
Each block below is the shipped default for that part ofvalues.yaml.
Image and Resources
image in the default (Community) tag series. The -oss tags are an Apache-only build that removes compression, continuous aggregates and retention policies. If you pin a different PostgreSQL major, match backup.image to it (see Backup).
timescaledb-tune sizes PostgreSQL’s memory and worker settings from the container limit only at first boot, while the data volume is empty. Raising resources.maxMemory on an existing deployment does not retune the server — change the settings with ALTER SYSTEM inside PostgreSQL, or reinstall on a fresh volume. On a stateful workload the ratio of maxCpu to minCpu may not exceed 4:1; raising maxCpu alone can cross that limit and is rejected when the workload is applied.Credentials
database key. The three keys are applied only when the volume is first initialized; changing the secret afterwards does not change the stored password — see Rotating the Password.
Storage
Internal Access
internalAccess can take several minutes to take effect — re-test before concluding it did not apply.
Public Access
PgBouncer
PgBouncer multiplexes many application connections into a small pool of real database connections. When enabled it becomes the endpoint your applications connect to, and it reads the same credentials secret and identity as the server — nothing extra to configure.Backup
A cron workload runspg_dumpall on the schedule and uploads a gzip-compressed SQL dump of every database and role to the bucket for the chosen provider. It authenticates with the username and password from your credentials secret. Each provider’s bucket, cloud account and secret steps are under Backing Up.
backup.image must match the server’s PostgreSQL major version: tag 18.1.0 for the default -pg18 image, 17.1.0 if you pin a -pg17 image.Connecting
Everything below is reachable from inside the GVC, subject tointernalAccess.type; the public endpoint exists only when publicAccess.enabled: true.
psql:
psql inside the container, where the credentials are already present as environment variables:
Using Hypertables
Any PostgreSQL client or ORM works unchanged. Turn a regular table into a hypertable (automatically partitioned by time) and query it with time buckets:timescaledb_information.jobs and timescaledb_information.job_errors views.
Operations
Backing Up
Backups are off by default. Enable them withbackup.enabled: true, pick a backup.provider, and complete that provider’s setup below first. The job writes postgres-TIMESTAMP.sql.gz objects under backup.PROVIDER.prefix in your bucket on every run of backup.schedule. Rehearse a backup and a restore before relying on either.
AWS S3
-
Create an S3 bucket. Set
backup.aws.bucketto its name andbackup.aws.regionto its region. -
If you do not have one yet, create a Control Plane cloud account for the AWS account holding the bucket. Set
backup.aws.cloudAccountNameto its name. -
Create an IAM policy scoped to exactly that bucket, replacing
YOUR_BUCKET_NAME:
- Set
backup.aws.policyNameto that policy’s name. The template attaches it to the workload identity and nothing else — the bucket in your policy is the only storage the backup job can reach.
GCS
-
Create a GCS bucket. Set
backup.gcp.bucketto its name. -
Create a Control Plane cloud account for the GCP project holding the bucket, and set
backup.gcp.cloudAccountNameto its name. Access is keyless — no stored credentials. -
Grant the cloud account’s service account the Storage Admin role (
roles/storage.objectAdminscoped to the bucket also works). The template additionally binds the identity toroles/storage.objectAdminon exactly the bucket inbackup.gcp.bucket.
MinIO
No cloud account is needed — the job authenticates with a second prerequisite secret.-
Create the bucket in MinIO. Set
backup.minio.bucketto its name. -
Set
backup.minio.endpointto the S3 API address including the port. For the MinIO template deployed in the same GVC that ishttp://WORKLOAD_NAME.GVC_NAME.cpln.local:9000. -
Create a dictionary secret holding exactly the keys
accessKeyandsecretKey, and setbackup.minio.credentialsSecretNameto its name. For the MinIO template these are theusernameandpasswordfrom its own credentials secret:
reveal on this secret as well as the database credentials secret, and on nothing else. Like the database credentials secret, it must exist before you install or upgrade with provider: minio — a missing secret wedges the backup workload the same way, and the render refuses an empty backup.minio.credentialsSecretName.
Restoring a Backup
Restoring TimescaleDB is not the vanilla PostgreSQL procedure. The target database must already have the TimescaleDB extension at the same version as the dump, and the replay must be wrapped intimescaledb_pre_restore() and timescaledb_post_restore() — the first stops the background workers and puts the database in restoring mode, the second brings it back. Skipping timescaledb_post_restore() leaves compression and retention jobs paused.
Each scheduled backup is a gzip-compressed pg_dumpall script that recreates every role and database it contains. Restore it into a fresh install running the same image tag as the one the dump was taken from: the first boot has already created your database with the extension, so you prepare that database, replay the script against the postgres maintenance database, then finish. Run the commands from a client that can reach both the bucket and the server — a workload inside the GVC, or your own machine with cpln port-forward RELEASE_NAME-timescaledb 5432:5432 --gvc GVC_NAME open and --host=127.0.0.1 in place of the internal hostname.
- AWS S3
- GCS
- MinIO
already exists errors for the role and database that the server created at first boot are expected; the rest of the script loads normally. If the dump holds additional databases, they are created during the replay without timescaledb_pre_restore() having run in them — restore those one at a time with the per-database procedure below instead.
Single database, upstream procedure. TimescaleDB’s own documentation describes a per-database pg_dump -Fc and pg_restore cycle. With cpln port-forward RELEASE_NAME-timescaledb 5432:5432 --gvc GVC_NAME open you can run it from your machine against this template; the target database must exist with the extension already created, and pg_restore must not use -j, which does not restore the TimescaleDB catalogs correctly:
Rotating the Password
The server reads the secret only when the volume is first initialized, so change the password inside PostgreSQL first, then update the secret to match:Upgrading From Earlier Versions
Three template versions changed what you must supply. An upgrade that still carries a removed key is refused at render, socpln helm upgrade fails and your existing release is left running rather than restarted against a different password.
Read the credentials the database already uses
Create the prerequisite secret with those same values
username, password and database. Different values here do not change the database — they only leave the workload unable to authenticate.Remove the old keys from your values
config.username, config.password and config.database, and set config.credentialsSecretName to your secret’s name. If you back up to MinIO, replace backup.minio.accessKey and backup.minio.secretKey with backup.minio.credentialsSecretName and create that secret as described under MinIO. If you back up to AWS, check your IAM policy against the action list under AWS S3.Upgrade, then rotate any default password
Scaling and Availability
- The server is pinned to one replica. Do not raise it — a single volume set backs a single server, and a second replica cannot mount it. Choose TimescaleDB Highly Available when you need failover.
- PgBouncer is stateless;
pgbouncer.replicasscales it horizontally for high connection counts. - Every
cpln helm upgraderestarts the server, including the first upgrade after an install even when nothing changed. Plan each one as a short write outage. - A node failure reschedules the server and reattaches the same volume. The exposure is minutes of downtime, not data loss.
Troubleshooting
Workload never becomes ready and cpln logs returns nothing
Workload never becomes ready and cpln logs returns nothing
cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-timescaledb"}' --limit 50 --since 10m returns zero lines.Cause: config.credentialsSecretName names a secret that does not exist, so the container is never started. The message is only visible in status.versions[].message:cpln workload force-redeployment RELEASE_NAME-timescaledb --gvc GVC_NAME. The same applies to RELEASE_NAME-timescaledb-backup when backup.minio.credentialsSecretName names a missing secret.Upgrade fails with 'config.username and config.password were REMOVED'
Upgrade fails with 'config.username and config.password were REMOVED'
cpln helm upgrade stops before touching any resource:Upgrade fails with 'backup.minio.accessKey and backup.minio.secretKey were REMOVED'
Upgrade fails with 'backup.minio.accessKey and backup.minio.secretKey were REMOVED'
cpln helm upgrade (or a fresh install) with backup.provider: minio stops at render:backup.minio.credentialsSecretName is refused with its own message: backup.minio.credentialsSecretName is required when provider is 'minio'.Cause: your values still carry the MinIO credential keys that were removed in 1.2.0, or do not name the replacement secret.Fix: create the MinIO credentials secret as described under MinIO, set backup.minio.credentialsSecretName, and delete the two old keys.Password changed in the secret but the old one still works
Password changed in the secret but the old one still works
password key in the credentials secret, but the server still accepts the previous password and rejects the new one.Cause: the secret is applied only when the volume is first initialized. Afterwards the stored password lives in the database, not the secret.Fix: change it inside PostgreSQL and then update the secret to match — see Rotating the Password.Compression, continuous aggregate or retention calls fail with 'function ... does not exist'
Compression, continuous aggregate or retention calls fail with 'function ... does not exist'
add_compression_policy, add_retention_policy or CREATE MATERIALIZED VIEW ... WITH (timescaledb.continuous) fails with a function ... does not exist style error, while hypertables work.Cause: image points at an -oss tag. Those are Apache-only builds with the Community (TSL) features removed.Fix: use a tag from the default series, such as the shipped timescale/timescaledb:2.28.3-pg18.Compression or retention jobs stop running after a restore
Compression or retention jobs stop running after a restore
timescaledb_information.jobs shows the policies but nothing executes, typically after a restore.Cause: timescaledb_pre_restore() was run and timescaledb_post_restore() was not. Background workers stay stopped until the second call.Fix: run SELECT timescaledb_post_restore(); in the affected database. Check timescaledb_information.job_errors for anything that failed in between.Queries through PgBouncer fail on SET, temporary tables or advisory locks
Queries through PgBouncer fail on SET, temporary tables or advisory locks
RELEASE_NAME-timescaledb directly fail or behave inconsistently through RELEASE_NAME-pgbouncer.Cause: pgbouncer.poolMode: transaction returns the server connection after every transaction, so session-level state is not preserved.Fix: switch to pgbouncer.poolMode: session (and raise defaultPoolSize to your expected concurrency), or connect such clients to the server directly.Apply rejected with 'The ratio between cpu and minCpu must be less than 4:1'
Apply rejected with 'The ratio between cpu and minCpu must be less than 4:1'
resources.maxCpu is more than four times resources.minCpu, which the platform rejects on a stateful workload.Fix: raise resources.minCpu or lower resources.maxCpu so the ratio is at most 4:1.Important Notes
- Create the credentials secret before installing. A reference to a secret that does not exist wedges the workload with no log output; see Prerequisites for the one command that shows the reason.
- Credentials are read only when the volume is first initialized. Rotate with
ALTER ROLEinside PostgreSQL, then update the secret — see Rotating the Password. - Tuning is captured at first boot only.
timescaledb-tunesizes memory settings from the container limit while the volume is empty; raisingresources.maxMemorylater does not retune. - Do not scale the server past one replica. It is a single instance on a single volume, not a replicated cluster.
- Keep the image tag in the default (Community) series.
-osstags remove compression, continuous aggregates and retention policies. Matchbackup.imageto the server’s PostgreSQL major. - Public access is unencrypted. The image ships no TLS certificates — keep
publicAccess.enabled: falseunless you accept plaintext connections. - Restores need
timescaledb_pre_restore()andtimescaledb_post_restore()around the replay, on a server with the same extension version — see Restoring a Backup. cpln helm uninstalldeletes the volume set and the database with it; a final snapshot is kept for 7 days. Your credentials secrets are yours and are left alone.- Every
cpln helm upgraderestarts the server. Treat each one as a short planned write outage.