Resharding Operations
July 29, 2026 · View on GitHub
Local development
Run the normal local checks with just build, just test-unit, and
just lint. Kubernetes-tagged reshard tests use the fake client and run under
just test-controlplane-k8s; they do not require a live cluster, though other
packages in that recipe may require the repository's Postgres test setup.
Runner pod resources default to 2 CPU and 8Gi memory. Override them with
DUCKGRES_RESHARD_POD_CPU and DUCKGRES_RESHARD_POD_MEMORY. Invalid
quantities fail the pod spawn with an operator-visible error; they never panic
the control plane.
Destination preflight rejection
A cnpg-shard reshard is rejected before operation creation unless the control
plane can read the destination's provisioner Secret and execute SELECT 1
against its primary service. Check the CNPG Cluster Ready condition, database
instance pods, PVCs, and init-job scheduling events. Pooler readiness alone
does not establish shard health. Fix the shard and retry; there is no reshard
operation to recover or cancel after a preflight rejection.
Consuming the resharding signal
The runner's first mutation is the advisory-locked warehouse
ready → resharding transition. Services using the control-plane API should
read GET /api/v1/warehouses and treat state: "resharding" (and therefore
writable: false) as the signal to stop or defer warehouse work. The warehouse
remains in the response throughout the operation. This lifecycle state is
server-managed; clients must not try to set it through the warehouse update
endpoint.
Failed or stale runner
-
Inspect the operation log and
duckgres-reshard-op-<id>pod events. -
Do not manually set the warehouse to
ready. The runner only unblocks it after a verified forward completion or verified rollback. -
Fix the scheduling, image, RBAC, config-store, or target connectivity error.
-
If automatic respawn paused after three attempts, reset only the operation's durable counter:
UPDATE duckgres_reshard_operations SET respawn_attempts = 0 WHERE id = <operation-id> AND state IN ('pending', 'running'); -
The leader reconciler will recreate the runner. A takeover never rediscovers the source from post-cutover Duckling status; it resumes only safe durable phases and otherwise rolls back.
Recovery remains blocked
If the operation is terminal-failed while the warehouse remains resharding,
read the final recovery observations before changing state. Confirm the
Duckling points at the intended source or target, its tenant role answers, and
the catalog fingerprint/table set is complete. Only then restore warehouse
readiness. For a damaged catalog, use the pg_restore command recorded beside
backup_s3_uri in the operation log.
Also inspect status.metadataStore.reshardMaintenance. A failed operation
must not be manually unblocked while its status says fenced=true: that means
the tenant role is still NOLOGIN. Repair the source pointer first, change the
maintenance phase to prepared, wait until status reports
tenantLogin=true and maintenanceLogin=true, then set the phase to
disabled and wait for maintenanceNoLogin=true. Terminate any remaining
sessions for the maintenance username, remove reshardMaintenance, and verify
every resource in its published resourceRefs is absent. Removing the field
before observing the factual login states loses the clearest declarative
recovery signal. The temporary role is operation-scoped and privileged; a
leftover maintenance identity, credential Secret, password generator,
ExternalSecret, Crossplane Usage, or transient RBAC object is a security
incident to clean up before admitting traffic.
One blocked shape is deliberate: when the op's recorded source identity was
unusable (empty/invalid from_shard, or an external source block without
endpoint/password secret), rollback refuses to emit the flip-back patch — the
XRD would reject it — and leaves the warehouse blocked with an ERROR carrying
the manual steps. The duckling then still points at the WRONG (target) store.
Determine where the catalog actually lives (duckling status history, the
pre-flip backup_s3_uri), patch spec.metadataStore to it, verify a client
can activate against the real catalog, and only then set the warehouse state
back to ready. Never unblock first — clients would activate against the
wrong (likely empty) catalog.
Never delete or recreate a retained cnpg database until the operation log shows that the external target passed content fingerprint verification.