Kvindo™ Cloud Docs
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.
• 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 restore — spec.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 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.
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.
| 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 |
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
Resource docs
More in this section