Kvindo™ Cloud Docs


Language

PostgreSQL Cluster

A PostgreSQL Cluster is a managed, horizontally-shardable PostgreSQL deployment built on Citus (distributed PostgreSQL) and Patroni (automated failover), coordinated by a dedicated etcd quorum the platform provisions and manages for you — it never appears in the spec. The cluster is one resource with an array of named shard groups in spec.shardGroups; the first one ever created is the coordinator and holds the cluster's distributed-table metadata.

A single shard group with one or more replicas is a plain HA PostgreSQL deployment — no sharding, no query-shape constraints. Add a second shard group only when you actually need to distribute data across nodes.
Key concepts

Shard groups, not shards — each entry in spec.shardGroups is a full Patroni group (one primary + spec.replicasPerShardGroup replicas), not a single row range; Citus shards individual distributed tables across whichever shard groups exist

The coordinator can never be removed or renamed away — the first shard group ever created is the coordinator for the cluster's lifetime; a modify that omits its name is rejected outright

Shard groups can't be swapped in one modify — adding a new shard group and removing an old one in the same request is rejected (it's indistinguishable from renaming one you meant to keep); do it as two separate modifies when you genuinely want to replace one

Scaling is one shard group per modify — the shard-group count may change by at most one in a single request, same discipline as Valkey's own shard scaling

No root password in the spec — unlike Standalone PostgreSQL, this resource has no user-facing superuser credential. Create a PostgreSqlRole (see below) to get an actual login; the internal bootstrap credential the platform generates for its own automation is never exposed through the API

Point-in-time restorespec.restoreConfiguration creates a brand-new cluster restored from another cluster's backups as of a specific UTC moment; immutable, create-time only, and the two clusters are otherwise independent

Public access — private by default; set spec.createPublicIpv4 for a public IPv4 per node, and spec.tlsMode to require to force encrypted connections (mandatory once public access is on)

Citus sharding constraints

Citus distributes tables by a chosen distribution column, and that choice shapes what queries stay fast. This is not a drop-in replacement for a single-node database once more than one shard group is in play — plan the schema around it:

Primary keys must include the distribution column — Citus cannot enforce global uniqueness on any other column

Foreign keys between distributed tables must reference the same distribution column, or the reference has to go through a reference table (a small table copied to every shard group instead of sharded)

Joins and transactions that span rows with different distribution-column values cross shard groups — still correct, but noticeably slower than a same-node query, since it involves a real network round trip between shard groups

Pick the distribution column deliberately — most applications shard on a tenant/customer/organization id, so that a single tenant's data (and its queries) stay within one shard group

None of this applies to a single-shard-group deployment — it behaves like ordinary PostgreSQL with Citus installed but never invoked.

License notice

Citus is licensed under the GNU Affero General Public License v3 (AGPLv3). Kvindo Cloud runs the unmodified upstream extension; its complete corresponding source code is publicly available from the upstream project at github.com/citusdata/citus, satisfying the AGPL's network-use source-availability requirement.

Parameters
UI Name API / kc name Terraform name Optional Format Default Is read only Description
Shard groups spec.shardGroups spec.shard_groups No list of objects No One entry per shard group — the first by id is the coordinator and can never be removed or replaced
Shard group name shardGroups[].name shard_groups[].name No string No The real identity — the server resolves it against this cluster's existing shard groups by name and reuses the same underlying group when it matches. Renaming is treated as removing the old one and adding a new one, deliberately, so don't rename a shard group you want to keep
VPC subnet shardGroups[].vpcSubnetId shard_groups[].vpc_subnet_id No ULID — references a VPC Subnet No Subnet for this shard group's instances
Replicas per shard group spec.replicasPerShardGroup spec.replicas_per_shard_group No integer No Extra VMs per shard group replicating the primary for failover
Parameters set spec.postgreSqlParametersSetId spec.postgresql_parameters_set_id Yes ULID — references a PostgreSqlParametersSet No postgresql.conf tuning applied cluster-wide
Version spec.version spec.version Yes string — PostgreSQL major version platform default No The major version is immutable for the cluster's lifetime once set
Backup retention spec.backupRetentionDays spec.backup_retention_days No integer — days No How long pgBackRest archives are kept in S3
Restore configuration spec.restoreConfiguration spec.restore_configuration Yes object No Point-in-time restore from another cluster's backups — immutable, create-time only
Source cluster restoreConfiguration.postgreSqlId restore_configuration.postgresql_id No ULID — references a PostgreSql cluster No The cluster whose backups to restore from
Restore time restoreConfiguration.restoreTime restore_configuration.restore_time No string — UTC timestamp No Data after this moment is not present in the restored cluster
VM offer spec.vmOfferId spec.vm_offer_id No string (≤32) — compute offer No Applies to every instance across every shard group; see the Console catalog
Volume offer spec.volumeOfferId spec.volume_offer_id No string (≤32) — disk offer No Applies to every instance
Volume size spec.volumeSizeGiB spec.volume_size_gib No integer — GiB No Applies to every instance
TLS mode spec.tlsMode spec.tls_mode Yes string — allow/require allow No require is mandatory once spec.createPublicIpv4 is set
Public IPv4 spec.createPublicIpv4 spec.create_public_ipv4 Yes boolean false No Give every node a public IPv4
Port status.port status.port integer Yes Client port — always 5432 today
Connection URI status.connectionUri status.connection_uri string Yes A starting point — a real client still needs to route reads/writes appropriately
Coordinator endpoint status.coordinatorEndpoint status.coordinator_endpoint string Yes host:port of the coordinator shard group's current primary
Primary endpoints status.primaryEndpoints status.primary_endpoints list of strings Yes host:port for each shard group's current primary
Cluster state status.clusterState status.cluster_state string Yes Reported directly from the underlying probe
Anti-affinity OK status.antiAffinityOk status.anti_affinity_ok boolean Yes False when a primary and one of its own replicas share a VM (degraded placement)
Anti-affinity message status.antiAffinityMessage status.anti_affinity_message string Yes Human-readable detail behind antiAffinityOk
Shard groups status.shardGroups status.shard_groups list of objects Yes Observed state per shard group
Is coordinator shardGroups[].isCoordinator shard_groups[].is_coordinator boolean Yes Whether this shard group is the cluster's coordinator
Primary endpoint shardGroups[].primaryEndpoint shard_groups[].primary_endpoint string Yes host:port of this shard group's current primary
Replica endpoints shardGroups[].replicaEndpoints shard_groups[].replica_endpoints list of strings Yes host:port for each of this shard group's replicas
Nodes status.nodes status.nodes list of objects Yes One entry per provisioned instance across all shard groups
Private IPv4 nodes[].privateIpV4 nodes[].private_ipv4 string Yes Address on the shard group's VPC subnet
Is primary nodes[].isPrimary nodes[].is_primary boolean Yes Whether this instance is currently its shard group's primary
Patroni state nodes[].patroniState nodes[].patroni_state string Yes Raw Patroni member state
Examples

A private 2-shard-group cluster (real Citus sharding) with one replica per shard group, on an existing subnet. Terraform and Python SDK support are planned for a later release — use the kc CLI or the REST API directly for now.

kc CLI


Related pages

Resource docs

More in this section

An unhandled error has occurred. Reload
Произошла непредвиденная ошибка. Перезагрузить 🗙