API Reference
Packages
pgcopydb-operator.io/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group.
Resource Types
CloneOptions
CloneOptions maps the pgcopydb clone surface. All fields are optional; a zero value means the operator decides, which for most fields is pgcopydb's own default. It overrides three: tableJobs follows the worker's CPU request, and splitTablesLargerThan and splitMaxParts turn on same-table concurrency. See docs/configuration.md.
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
allDatabases boolean |
allDatabases clones the whole instance, including postgres, and creates missing target databases; roles are implied. Both connections must name a maintenance database and use superuser roles. Filters and skips apply to every database; job counts are global across databases. |
Optional: {} |
|
tableJobs integer |
tableJobs is the number of concurrent table COPY workers (pgcopydb --table-jobs). Unset follows the worker's CPU request, minimum four. Each job also gets a concurrent VACUUM ANALYZE backend on the target, so N here means up to 2N target connections. |
Minimum: 1 Optional: {} |
|
indexJobs integer |
indexJobs is the number of concurrent CREATE INDEX workers (--index-jobs). Unset leaves pgcopydb's default of four. Size it against the TARGET, not the worker: pgcopydb sets maintenance_work_mem to 1GB per index worker, overriding the server's own setting, so four jobs authorise 4GB there. |
Minimum: 1 Optional: {} |
|
restoreJobs integer |
restoreJobs is pg_restore --jobs (--restore-jobs); 0 follows indexJobs. | Minimum: 0 Optional: {} |
|
largeObjectsJobs integer |
largeObjectsJobs is the number of concurrent large-object workers. | Minimum: 1 Optional: {} |
|
splitTablesLargerThan Quantity |
splitTablesLargerThan enables same-table concurrency for tables at or above this size (--split-tables-larger-than), rendered to bytes. Unset defaults to 512Mi. Splitting needs a single-column integer key, or it falls back to ctid ranges. See docs/operations/performance.md. |
Optional: {} |
|
splitMaxParts integer |
splitMaxParts caps the number of parts per table (--split-max-parts). Unset defaults to 8, so a very large table cannot fan out into hundreds of parts and catalog rows. |
Minimum: 0 Optional: {} |
|
estimateTableSizes boolean |
estimateTableSizes bases split decisions on pg_class page-count estimates instead of exact size queries (--estimate-table-sizes). To refresh those, pgcopydb first runs vacuumdb --analyze-only (with tableJobs workers) on the SOURCE; add "analyze" to skip to leave the source untouched. |
Optional: {} |
|
dropIfExists boolean |
dropIfExists issues pg_restore --clean --if-exists on the target. | Optional: {} |
|
roles boolean |
roles copies roles before the clone (--roles). Needs superuser on the source unless noRolePasswords is also set. |
Optional: {} |
|
noRolePasswords boolean |
noRolePasswords dumps roles without passwords (--no-role-passwords), avoiding the superuser requirement of roles, but not of allDatabases. |
Optional: {} |
|
noOwner boolean |
noOwner skips ALTER OWNER on restore (--no-owner). | Optional: {} |
|
ownerAfterRestore string |
ownerAfterRestore hands the restored objects to this role once the worker has finished. Needs noOwner: true, or pg_restore assigns the source owners and the handover covers only part of the schema. Immutable. The operator quotes the name as an identifier, so give it unquoted. See docs/reference/prerequisites.md. |
MaxLength: 63 MinLength: 1 Pattern: ^[^"\x00-\x1F\x7F]+$ Optional: {} |
|
noACL boolean |
noACL skips GRANT/REVOKE on restore (--no-acl). | Optional: {} |
|
noComments boolean |
noComments skips COMMENT statements (--no-comments). | Optional: {} |
|
noTablespaces boolean |
noTablespaces skips tablespace selection (--no-tablespaces). | Optional: {} |
|
useCopyBinary boolean |
useCopyBinary uses COPY WITH (FORMAT BINARY) (--use-copy-binary), on by default. pgcopydb falls back to text for any table with a column whose binary encoding is not safe, so the choice is per table. Set it false to force text everywhere. See docs/operations/performance.md. |
true | Optional: {} |
failFast boolean |
failFast stops the whole run on the first failed child (--fail-fast). | Optional: {} |
|
skip SkipOption array |
skip lists base-copy sections to skip. | Enum: [largeObjects extensions extensionComments collations vacuum analyze dbProperties ctidSplit] Optional: {} |
|
filters Filters |
filters is rendered to the pgcopydb --filters INI file. | Optional: {} |
CloneProgress
CloneProgress carries how far the base copy has got. While the copy runs
the operator counts relations on both databases with psql; pgcopydb's own
list progress replaces that wherever it can be read.
Appears in: - MigrationStatus
| Field | Description | Default | Validation |
|---|---|---|---|
tablesTotal integer |
Optional: {} |
||
tablesDone integer |
Optional: {} |
||
indexesTotal integer |
Optional: {} |
||
indexesDone integer |
Optional: {} |
||
bytesTotal Quantity |
bytesTotal is the total bytes to copy: the in-scope tables' size on the source, or pgcopydb's own figure once it has answered. |
Optional: {} |
|
bytesDone Quantity |
bytesDone is the bytes copied so far. | Optional: {} |
|
observedAt Time |
observedAt is when a live sample last wrote these figures. A failed sample leaves it and them unchanged; pgcopydb's own counts carry none. |
Optional: {} |
ConnectionSecret
ConnectionSecret points at a Secret whose keys hold the parts of a connection. Key names are remappable; defaults match the common platform convention (DB, PW, URL, URL_EXTERNAL, USER).
Appears in: - PostgresConnection
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
name is the Secret in the Migration's namespace. | MinLength: 1 Required: {} |
|
endpoint string |
endpoint picks which URL key supplies the host when the database key holds a bare name: internal (url key) or external (urlExternal key). |
internal | Enum: [internal external] Optional: {} |
keys ConnectionSecretKeys |
keys remaps the Secret key names. | Optional: {} |
ConnectionSecretKeys
ConnectionSecretKeys names the Secret keys the connection parts come from.
Appears in: - ConnectionSecret
| Field | Description | Default | Validation |
|---|---|---|---|
database string |
database is a bare database name or a libpq URI that MUST be password-free (the password key carries it); a URI is authoritative for user, host, port, and database name. Values are used literally: special characters need uriSecretRef. |
DB | Optional: {} |
password string |
password holds the password; projected as a file, never env or argv. The key MUST exist even when the database key holds a URI. |
PW | Optional: {} |
url string |
url holds the internal hostname, optionally host:port. | URL | Optional: {} |
urlExternal string |
urlExternal holds the externally reachable hostname, optionally host:port. | URL_EXTERNAL | Optional: {} |
username string |
username holds the role to connect as. | USER | Optional: {} |
CutoverMode
Underlying type: string
CutoverMode picks who pulls the trigger.
Validation: - Enum: [Manual Automatic]
Appears in: - CutoverSpec
| Field | Description |
|---|---|
Manual |
CutoverManual waits for approval and confirmed catch-up. |
Automatic |
CutoverAutomatic cuts over as soon as the migration is caught up. |
CutoverSpec
CutoverSpec controls when replication stops and the migration finalizes. Cutover means: writes to the source MUST already be stopped, the stream is frozen at the source's current LSN, drained, and sequences re-synced.
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
mode CutoverMode |
mode selects Manual (default) or Automatic cutover. | Manual | Enum: [Manual Automatic] Optional: {} |
approved boolean |
approved arms Manual cutover; confirmed catch-up starts it. Mutable. Setting it back to false after cutover started has no effect. |
Optional: {} |
Filters
Filters maps the pgcopydb --filters INI sections. pgcopydb rejects some combinations (for example include-only-table with exclude-table); those are enforced by CEL below and surfaced as validation errors.
Appears in: - CloneOptions
| Field | Description | Default | Validation |
|---|---|---|---|
includeOnlyTables string array |
Optional: {} |
||
excludeTables string array |
Optional: {} |
||
includeOnlySchemas string array |
Optional: {} |
||
excludeSchemas string array |
Optional: {} |
||
excludeIndexes string array |
Optional: {} |
||
excludeTableData string array |
Optional: {} |
||
includeOnlyExtensions string array |
Optional: {} |
||
excludeExtensions string array |
Optional: {} |
FollowOptions
FollowOptions enables live migration: clone under a replication slot, then stream and apply changes until cutover (pgcopydb clone --follow).
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
enabled boolean |
enabled turns the migration into a live one. | Optional: {} |
|
plugin string |
plugin is the logical decoding plugin (--plugin). | pgoutput | Enum: [pgoutput wal2json test_decoding] Optional: {} |
slotName string |
slotName overrides the replication slot name (--slot-name). Empty means a generated name unique to this Migration; set it only when deliberately fanning several migrations out of one source. The pattern is PostgreSQL's own slot-name charset, which the operator relies on when it interpolates it into SQL. |
MaxLength: 63 Pattern: ^[a-z0-9_]+$ Optional: {} |
|
publication string |
publication names a pre-created publication (--publication); empty lets pgcopydb create and drop its own. |
Optional: {} |
|
wal2jsonNumericAsString boolean |
wal2jsonNumericAsString makes wal2json emit numeric values as JSON strings (--wal2json-numeric-as-string), preserving precision a JSON number would lose. Only meaningful with plugin wal2json; admission rejects it under any other plugin. |
Optional: {} |
|
replayNoOpUpdates boolean |
replayNoOpUpdates replays UPDATEs that change no columns (--replay-no-op-updates), needed when target triggers must fire. |
Optional: {} |
|
allowMissingReplicaIdentity string array |
allowMissingReplicaIdentity acknowledges tables the preflight replica-identity audit would otherwise fail on, as schema-qualified names exactly as the preflight prints them ("*" covers every offender). UPDATE or DELETE on an acknowledged table still fails on the source at write time, so acknowledge only read-only or insert-only ones. Immutable with follow. |
Optional: {} |
|
maxCatchupLag Quantity |
maxCatchupLag is the replication lag under which the migration counts as caught up (the CaughtUp condition and Automatic cutover trigger). |
16Mi | Optional: {} |
Migration
Migration copies PostgreSQL data from a source endpoint to a target, optionally following changes until cutover.
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
pgcopydb-operator.io/v1beta1 |
||
kind string |
Migration |
||
metadata ObjectMeta |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec MigrationSpec |
spec is the migration to run; source and target are immutable. | Required: {} |
|
status MigrationStatus |
status reports progress. Conditions are authoritative; phase summarizes them. | Optional: {} |
MigrationPhase
Underlying type: string
MigrationPhase summarizes conditions and worker progress for the printer column. Initial Pending records the controller's first observation, not an API-server default. Conditions are authoritative after this bootstrap observation.
Validation: - Enum: [Pending Validating Cloning Finalizing Streaming CutoverPending CuttingOver Verifying Completed Failed Suspended]
Appears in: - MigrationStatus
| Field | Description |
|---|---|
Pending |
PhasePending is the first phase persisted by the controller for a new Migration. API-server creation does not initialize status. |
Validating |
|
Cloning |
|
Finalizing |
PhaseFinalizing is the tail of a base copy: data across, worker building indexes, applying constraints and vacuuming, and on a clone-only migration the ownerAfterRestore handover. The target stops growing, so size-based estimates read as finished. See docs/operations/performance.md#the-vacuum-tail. |
Streaming |
|
CutoverPending |
|
CuttingOver |
|
Verifying |
|
Completed |
|
Failed |
|
Suspended |
MigrationSpec
MigrationSpec is the desired state of a Migration. source and target are immutable after creation (a migration is a one-shot job, like batch/v1 Job).
Appears in: - Migration
| Field | Description | Default | Validation |
|---|---|---|---|
source PostgresConnection |
source is the PostgreSQL endpoint to migrate from. Immutable. | Required: {} |
|
target PostgresConnection |
target is the PostgreSQL endpoint to migrate to. Immutable. | Required: {} |
|
clone CloneOptions |
clone configures the base copy. | Optional: {} |
|
follow FollowOptions |
follow enables live migration (CDC after the base copy). Immutable: a one-shot clone cannot become a live migration after the fact. |
Optional: {} |
|
cutover CutoverSpec |
cutover controls how a live migration ends; ignored without follow. | Optional: {} |
|
verification VerificationOptions |
verification runs pgcopydb compare checks once the migration reaches its success path (clone: after the copy; follow: after cutover drained and replication state is cleaned up). |
Optional: {} |
|
workVolume WorkVolume |
workVolume configures the work-directory PVC. | Optional: {} |
|
runner RunnerSpec |
runner configures the worker pod. | Optional: {} |
|
suspend boolean |
suspend stops the worker while preserving the work volume. | Optional: {} |
|
dryRun boolean |
dryRun runs the preflight checks and stops: no worker Job, no data written, no replication slot, publication, or origin. A passed dry run ends Completed with reason DryRunSucceeded. Grants a superuserSecretRef would apply are reported, not applied. Unrelated to kubectl --dry-run. Immutable: the real run is a separate Migration. |
Optional: {} |
|
backoffLimit integer |
backoffLimit is the operator-level retry budget. Each attempt is a fresh Job (backoffLimit 0) that resumes via the pgcopydb work directory. |
3 | Minimum: 0 Optional: {} |
ttlSecondsAfterFinished integer |
ttlSecondsAfterFinished deletes owned Jobs this long after completion. | Minimum: 0 Optional: {} |
MigrationStatus
MigrationStatus is the observed state of a Migration.
Appears in: - Migration
| Field | Description | Default | Validation |
|---|---|---|---|
observedGeneration integer |
observedGeneration is the .metadata.generation last reconciled. | Optional: {} |
|
phase MigrationPhase |
phase summarizes conditions and worker progress after the controller's initial Pending observation. |
Enum: [Pending Validating Cloning Finalizing Streaming CutoverPending CuttingOver Verifying Completed Failed Suspended] Optional: {} |
|
conditions Condition array |
conditions represent the current state of the Migration. | Optional: {} |
|
attempts integer |
attempts is the number of worker Jobs created so far. | Optional: {} |
|
progress CloneProgress |
progress reports base-copy progress. | Optional: {} |
|
replication ReplicationStatus |
replication reports streaming state while following. | Optional: {} |
|
verification VerificationResult array |
verification reports each requested compare check separately, because the Verified condition collapses them and its reason names only the first mismatch. Re-derived from the compare Jobs every reconcile. |
Optional: {} |
|
jobName string |
jobName is the current worker Job. | Optional: {} |
|
startedAt Time |
Optional: {} |
||
completedAt Time |
Optional: {} |
PostgresConnection
PostgresConnection describes how to reach one PostgreSQL endpoint. Provide exactly one form: the inline fields (host/database/username plus a password secret), uriSecretRef (a full libpq URI/DSN), or secretRef (one Secret holding the parts as individual keys).
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
host string |
host is the server hostname or IP, for the inline form. | Optional: {} |
|
port integer |
port is the server port. | 5432 | Maximum: 65535 Minimum: 1 Optional: {} |
database string |
database is the database name to connect to, for the inline form. | Optional: {} |
|
username string |
username is the role to connect as, for the inline form. | Optional: {} |
|
passwordSecretRef SecretKeySelector |
passwordSecretRef selects the password. Rendered into a libpq passfile, never into argv or CR status. |
Optional: {} |
|
sslMode string |
sslMode is the libpq sslmode. | prefer | Enum: [disable allow prefer require verify-ca verify-full] Optional: {} |
tls TLSSecretRefs |
tls references client certificate material, mounted 0600 for libpq. | Optional: {} |
|
uriSecretRef SecretKeySelector |
uriSecretRef selects a full libpq connection URI/DSN (with credentials). Mutually exclusive with the inline fields; useful for DBaaS sources. |
Optional: {} |
|
secretRef ConnectionSecret |
secretRef references one Secret carrying the connection details as individual keys, the way platform provisioners hand them out. Mutually exclusive with the inline fields and uriSecretRef. |
Optional: {} |
|
superuserSecretRef ConnectionSecret |
superuserSecretRef names a superuser on this same endpoint, in the same Secret convention (USER/PW; URL keys, when present, must match this connection). The preflight uses it to verify and apply missing grants; applied statements are logged and kept, never reverted. |
Optional: {} |
ReplicationStatus
ReplicationStatus records source-visible feedback and the operator's cutover LSN.
Appears in: - MigrationStatus
| Field | Description | Default | Validation |
|---|---|---|---|
slotName string |
Optional: {} |
||
writeLSN string |
writeLSN is the walsender's write position, with slot confirmed-flush fallback when the migration role cannot read it. |
Optional: {} |
|
replayLSN string |
replayLSN is source-visible replay feedback, with slot confirmed-flush fallback. It may include certified idle WAL beyond the last applied data transaction. Post-cutover drain verification, not this position, proves target application. |
Optional: {} |
|
endpos string |
endpos is the cutover LSN once set. | Optional: {} |
|
lagBytes integer |
lagBytes is the byte distance between the source WAL head and replayLSN. | Optional: {} |
RunnerSpec
RunnerSpec configures the migration worker pod.
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
image string |
image overrides the runner image (default: operator-configured). | Optional: {} |
|
resources ResourceRequirements |
resources sets the runner container resource requirements. | Optional: {} |
|
nodeSelector object (keys:string, values:string) |
Optional: {} |
||
tolerations Toleration array |
Optional: {} |
||
affinity Affinity |
Optional: {} |
SkipOption
Underlying type: string
SkipOption names a section of the base copy to skip. Maps to pgcopydb --skip-* flags; CDC (follow) is unaffected by these. extensionComments (--skip-ext-comments) is already implied by extensions; list it alone to install extensions but drop their COMMENT statements.
Validation: - Enum: [largeObjects extensions extensionComments collations vacuum analyze dbProperties ctidSplit]
Appears in: - CloneOptions
TLSSecretRefs
TLSSecretRefs points at client certificate material for a connection.
Appears in: - PostgresConnection
| Field | Description | Default | Validation |
|---|---|---|---|
rootCA SecretKeySelector |
rootCA is the server CA bundle (libpq sslrootcert). | Optional: {} |
|
cert SecretKeySelector |
cert is the client certificate (libpq sslcert). | Optional: {} |
|
key SecretKeySelector |
key is the client private key (libpq sslkey). | Optional: {} |
VerificationOptions
VerificationOptions selects post-migration pgcopydb compare checks, both off by default because both are expensive. Results are information, not a gate: a mismatch sets Verified to False and emits a warning event, but the Migration still completes. Mutable until completion. See docs/operations/verification.md.
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
schema boolean |
schema runs pgcopydb compare schema: tables, columns, indexes, constraints, and sequence values as pgcopydb models them. Not a full DDL diff (no functions, triggers, ACLs, defaults). |
Optional: {} |
|
data boolean |
data runs pgcopydb compare data: per-table row counts and full-table checksums. Expensive: budget a sequential scan of every table on both sides. |
Optional: {} |
VerificationResult
VerificationResult is one compare check's outcome.
Appears in: - MigrationStatus
| Field | Description | Default | Validation |
|---|---|---|---|
check string |
check is the pgcopydb compare subcommand: schema or data. | Enum: [schema data] |
|
passed boolean |
passed is false when that compare reported differences. |
WorkVolume
WorkVolume configures the PVC that holds the pgcopydb work directory. This is the unit of resumability and MUST survive pod restarts.
Appears in: - MigrationSpec
| Field | Description | Default | Validation |
|---|---|---|---|
storageClassName string |
storageClassName selects the StorageClass; empty uses the cluster default. | Optional: {} |
|
size Quantity |
size is the requested volume size. | 10Gi | Optional: {} |