TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

Reading CloudNativePG: The Manager at PID 1, the Plugin Beyond the Socket, and the Journey of a Single WAL Slice

Status: Draft (2026-10-17), partially measured. Baseline versions: cloudnative-pg v1.30.0 (commit 4b5e244a7d03), plugin-barman-cloud v0.14.0 (1e13020fe5f0), cnpg-i v0.6.0 (844d20b2b783), cnpg-i-machinery v0.4.2 (e3ead2b31db4). Because a small cluster is running precisely these versions (operator 1.30.0, plugin v0.14.0), actual measurements were taken on that cluster on 2026-10-17. Read-only and obtained through (CR reading, pod configuration reading, running pod internal /proc·Reading configuration files, reading logs). Write, restart, and recovery tests were not performed.Writing rules: Actual measurement data is the basis, items that could not be measured are marked as "Unmeasured", and items that could not be confirmed are marked as "Unconfirmed".

Table of Contents

1. One-line summary: A "Resident Manager" and an "Outsourced Delivery Driver" attached to PostgreSQL

When running PostgreSQL on Kubernetes, the hard part is not spinning up pods, but rather determining the primary, replacing it when it dies, and faithfully transporting WALs externally. CloudNativePG (CNPG) does not use StatefulSets; instead, it creates pods and PVCs directly, and places a resident manager(instance manager) as PID 1 inside each pod to supervise PostgreSQL as a child process.

In recent versions, "transporting goods," which refers to backups and WAL archiving, is being detached from the main operator body and entrusted to an outsourced delivery driver(plugin). The contract between the two is a gRPC interface called CNPG-I, and the delivery driver built directly by the CNPG project is the barman-cloud plugin. This is designed so that the main body does not need to know the specifics of S3, GCS, or Azure, and the plugin can be updated independently of the main release.

Component Role Where it runs
CNPG Operator Reconciles Cluster, Backup, Pooler, etc., creates pods, PVCs, and services, and decides failover cnpg-system Deployment
Instance Manager(manager instance run) Runs PostgreSQL as a child, writes configuration files, and provides status HTTP endpoints PID 1 of the instance Pod
manager wal-archive / wal-restore PostgreSQL's archive_command·restore_command One-off commands invoked by Instance Pod, once per WAL
barman-cloud plugin, operator half Watches Cluster, prepares RBAC, and creates patches to inject sidecars into Pods cnpg-system Deployment of
barman-cloud plugin, instance half WAL archiving and restoration, base backups, and metrics Sidecar of the instance Pod
ObjectStore CR Which bucket, with what credentials, and using what compression App namespace

2. Architecture Diagram

오퍼레이터, 플러그인 두 반쪽, 인스턴스 파드 cnpg-system 네임스페이스 CNPG 오퍼레이터 Cluster 컨트롤러 Backup 컨트롤러 Plugin 컨트롤러 플러그인 저장소 (gRPC 연결 풀) barman-cloud operator 반쪽 Identity ReconcilerHooks OperatorLifecycle Deployment 1개 gRPC mTLS 인스턴스 파드 (DB 한 대) postgres 컨테이너 PID 1: manager (instance run) └ postgres (자식) └ wal-archive (매번) plugin-barman-cloud instance 반쪽 네이티브 사이드카 WAL · Backup Metrics 소켓 init: bootstrap-controller → manager 복사 상태 조회 /pg/status 사이드카 주입 패치 barman-cloud-* S3 호환 객체 저장소 ObjectStore CR 어디에·어떤 자격으로 소켓: 두 컨테이너가 같이 붙인 /plugins 볼륨의 유닉스 소켓. 오퍼레이터 ↔ 플러그인 Deployment 는 Service 로 찾는다.
Figure: Operator, the two plugin halves, and the instance Pod

How to read the diagram:

3. Code Map

Looking at four repositories together. Only the most important parts from the top level are selected.

Path What First file to read
cloudnative-pg api/v1/ Go types and helper functions for CRDs like Cluster and Backup cluster_types.go, backup_funcs.go
cloudnative-pg internal/controller/ Operator reconcile loops (Cluster, Backup, Plugin ...) cluster_controller.go, backup_controller.go
cloudnative-pg internal/cnpi/plugin/ CNPG-I client: plugin discovery, connection pool, RPC wrapper repository/setup.go, client/wal.go
cloudnative-pg internal/cmd/manager/ Subcommands in a single binary (instance run, wal-archive, backup …) instance/run/cmd.go, walarchive/cmd.go
cloudnative-pg pkg/management/postgres/ Instance manager core: PostgreSQL execution, web server, archiver archiver/archiver.go, webserver/local.go
cloudnative-pg pkg/postgres/ PostgreSQL configuration rules (including mandatory values) configuration.go
cnpg-i proto/ Interface definitions (9 services) identity.proto, wal.proto
cnpg-i-machinery pkg/pluginhelper/ gRPC server skeleton for plugins, object decoder http/server.go
plugin-barman-cloud internal/cnpgi/ Plugin implementation: operator/(Deployment half), instance/(sidecar half), common/(WAL) operator/lifecycle.go, common/wal.go
plugin-barman-cloud api/v1/ ObjectStore CRD objectstore_types.go

4. Following the Core Path

4.1 Cluster Reconcile Loop: Loading Plugins First

Reconcile (internal/controller/cluster_controller.go:169) reads the Cluster and first collects the names of the plugins used by this cluster(This is a combined list of plugins specified in thegetPluginsNeededForReconcile, :298). .spec.plugins and external clusters. It acquires connections to those names within 5 seconds and places them into theWithPlugins, internal/cnpi/plugin/client/client.go:79) context before entering the inner loop. If a plugin cannot be found, the phase is changed to "Unknown plugin" and checked again after 10 seconds. This is to avoid silently ignoring a plugin that is specified but not visible.

The inner reconcile, :310 is long but follows a clear sequence.

  1. Filling in defaults, determining images, updating plugin status, and creating auxiliary objects (Secret, Service, PDB) (createPostgresClusterObjects, cluster_create.go:57).
  2. plugin's pre-reconcile hook (preReconcilePluginHooks, plugins.go:36). Here, barman-cloud creates the Role and RoleBinding for the sidecar to read ObjectStore and Secret (Section 4.5).
  3. Querying the status of each instance via HTTPS (GetStatusFromInstances, pkg/management/postgres/webserver/client/remote/instance.go:183). If two primaries appear, do nothing and check again in 5 seconds. This waits for the returning old primary to demote itself, preventing data split-brain.
  4. Handling switchover/failover and reconciling Pods and PVCs (reconcileResources, :825).
  5. Finally, running the plugin post-hook, synchronizing status, and recording the "healthy" phase (finalizeReconciliation, plugins.go:105).

Plugins also intervene when the operator creates objects in Kubernetes. The operator's client wraps Create·Patch·Delete to first call the plugin's LifecycleHook (extendedClient.Create, internal/cnpi/plugin/operatorclient/client.go:71). NewInstance, pkg/specs/pods.go:485 which creates the instance Pod spec, also calls the same hook at the end with the "evaluate" action. Because Pods are actually created with the JSON patch returned by the plugin applied, sidecar injection occurs without a webhook.

4.2 How the Operator Finds Plugins: A Service and a Socket Folder

Plugins are discovered through two paths.

Regardless of the path, the actions taken immediately after connection are the same. LoadPlugin, internal/cnpi/plugin/connection/connection.go:442 It queries the name, version, and implemented servicesvia the Identity service, and then queries detailed capabilities for each implemented service. All subsequent calls are filtered by this capability list. For example, WAL archiving only goes to plugins with the ARCHIVE_WAL capability.

CNPG-I services are defined in cnpg-i/proto/ , totaling nine. They are Identity(identity.proto:23), Operator, OperatorLifecycle, ReconcilerHooks, WAL(wal.proto:23), Backup, RestoreJobHooks, Postgres, and Metrics. The entire Cluster object is sent as JSON with every request. This ensures that plugins do not need to re-read the Cluster from Kubernetes, and allows decisions to be made based on the exact state of the Cluster as seen by the operator at that moment.

Counting the RPCs actually called in the baseline operator code (grep for*Client().<RPC> call sites), Status· SetFirstRequired of the WAL service and Deregister of the Operator service could not be found anywhere they are called. They appear to be slots that exist in the proto but are not yet used by the 1.30.0 operator (intent unverified).

The plugin-side server skeleton is provided by cnpg-i-machinery. Server.Start, pkg/pluginhelper/http/server.go:152 registers the Identity first and lets the "enricher" functions attach the rest of the services. Depending on whether a server address is provided, it opens either a TCP or a Unix socket with the plugin name (createListener, :304).

4.3 Instance Manager: PID 1 is not PostgreSQL

The command of the instance pod is /controller/manager instance run (Section 6 measured). This binary is what the bootstrap-controller init container copied to the shared volume (bootstrap NewCmd, internal/cmd/manager/bootstrap/cmd.go:34). runSubCommand, internal/cmd/manager/instance/run/cmd.go:157 ). Reading the reveals that this PID 1 is essentially asmall controller manager. It hosts the instance, database, and role reconcilers, log pipe, PostgreSQL lifecycle manager, remote and local web servers, and metrics server on top of controller-runtime.

PostgreSQL is spawned by the lifecycle manager (runPostgresAndWait, internal/cmd/manager/instance/run/lifecycle/run.go:40). After waiting for initialization to complete (matching the signal file for the role to start), it executes postmaster as a child. When postmaster terminates, the manager also detects this and determines the next action. This is why PID 1 is the manager rather than PostgreSQL. Decoupling the unit by which Kubernetes kills and restarts containers from the unit by which PostgreSQL is stopped and restarted allows operations like reloading configuration or forcing a primary demotion without restarting the container .

The endpoint queried by the operator in step 3 of Section 4.1 is the remote web server's /pg/status (pgStatus, pkg/management/postgres/webserver/remote.go:320). Conversely, one-off commands inside the pod (wal-archive, backup) delegate work to PID 1 via the local web server or retrieve the Cluster cache.

4.4 Journey of a WAL Slice: From archive_command to S3

WAL 한 조각과 백업 한 번이 가는 길 ① WAL 아카이브 ② 백업(Backup CR) postgres archiver archive_command 실행 manager wal-archive PID 1 과 같은 바이너리 archiveWALViaPlugins /plugins 소켓을 훑는다 WAL.Archive (gRPC) 사이드카가 받는다 barman-cloud-wal-archive --gzip, 한 조각 약 0.25초 조건 갱신 ContinuousArchiving=True ScheduledBackup 매일 한 번 Backup 을 만든다 Backup 컨트롤러 checkPrerequisites method 가 plugin 인가? 예 → 플러그인 이름만 확인 아니오 → .spec.backup 필요 파드 안에서 exec manager backup 「이름」 Backup.Backup (gRPC) 로컬 웹서버 → 사이드카 barman-cloud-backup 끝나면 phase=completed destinationPath / serverName / wals·base serverName 은 Cluster 의 플러그인 파라미터에서 #1166 이 다룬 오류 method 생략 → 기본값 → no backup section #1164 이 다룬 자리 serverName 은 ObjectStore 가 아니라 플러그인 파라미터
Figure: The path taken by a WAL slice and a backup
  1. archive_command users cannot change. CNPG locks this value as a "mandatory configuration" (pkg/postgres/configuration.go:589, CnpgConfigurationSettings.MandatorySettings). The value is /controller/manager wal-archive --log-destination … %p . Regardless of the backup method used, the PostgreSQL-side configuration remains identical as a single line, and only the Go code behind it changes.
  2. wal-archive command. NewCmd, internal/cmd/manager/walarchive/cmd.go:40 fetches the Cluster from the local web server's cache and calls archiver.Run, pkg/management/postgres/archiver/archiver.go:124 . If it is not currently the primary (during a transition), it rejects the request. This is to prevent two nodes from uploading the same WAL simultaneously. Upon completion, success or failure is recorded in the Cluster via a ContinuousArchiving condition.
  3. Plugins first. internalRun, :156 's first action is to delegate to plugins.
	// We allow plugins to archive WALs even if there is no plugin
	// directly enabled by the user, to retain compatibility with
	// the old API.
	if err := archiveWALViaPlugins(ctx, cluster, pgData, walName); err != nil {
		return err
	}

	// If the used chosen a plugin to do WAL archiving, we don't
	// trigger the legacy archiving process.
	if cluster.GetEnabledWALArchivePluginName() != "" {
		return nil
	}

Source: cloudnative-pg v1.30.0 pkg/management/postgres/archiver/archiver.go, Apache-2.0

.spec.plugins[] If there is a isWALArchiver: true plugin, the legacy (in-tree) barman path is bypassed entirely. If none exists, it checks for .spec.backup.barmanObjectStore below that, and if that is also absent, it does nothing and returns success. Even for a Cluster without backup configured, archive_mode is enabled and the same command runs, but WALs are not uploaded anywhere and are treated as successful (Section 6 measured). 4. Scanning sockets for gRPC. archiveWALViaPlugins, :277 selects only the sockets from /plugins that belong to plugins enabled in the Cluster, and ArchiveWAL, internal/cnpi/plugin/client/wal.go:34 calls WAL.Archive carrying the Cluster JSON and the WAL path. The architecture spawns a new process and establishes a new connection for every single WAL. 5. Received by the sidecar. The plugin's WALServiceImplementation.Archive, internal/cnpgi/common/wal.go:107 extracts the plugin parameters (barmanObjectName, serverName) from the Cluster JSON, reads the ObjectStore to create credentials as environment variables, verifies if the target path is empty if it is the first time, collects additional prepared WALs up to maxParallel , and executes barman-cloud-wal-archive in parallel. The argument specifying the path includes configuration.ServerName (:196). This value connects to the serverName discussion in Section 5.

archive_command If fails, PostgreSQL retries the same WAL, and since pg_wal accumulates in the meantime, a break in any link of this chain ultimately manifests as a full disk. The exit code of the barman CLI is wrapped in a gRPC error string and returned (Section 6).

4.5 barman-cloud Plugin: One Binary, Two Halves

The subcommands of the plugin binary are four: instance·operator·restore·healthcheck (cmd/manager/main.go:52).

4.6 A Backup Execution: method Chooses the Path

BackupReconciler.Reconcile, internal/controller/backup_controller.go:127 locates the Cluster and begins with formal preconditions (checkPrerequisites, :390).

	if backup.Spec.Method == apiv1.BackupMethodPlugin {
		if len(cluster.Spec.Plugins) == 0 {
			const message = "cannot proceed with the backup as the cluster has no plugin configured"
			return flagMissingPrerequisite(message, "ClusterHasNoBackupExecutorPlugin")
		}

		return nil, nil
	}

	if cluster.Spec.Backup == nil {
		const message = "cannot proceed with the backup as the cluster has no backup section"
		return flagMissingPrerequisite(message, "ClusterHasBackupConfigured")
	}

Source: cloudnative-pg v1.30.0 internal/controller/backup_controller.go, Apache-2.0

method: plugin If it is , it simply checks whether at least one plugin exists and passes. All other methods require .spec.backup . Failures terminate with TerminalError and are not retried, because endlessly retrying a backup with incorrect configurations is pointless.

Once passed, paths diverge based on the method. plugin and barmanObjectStore are backups performed by the instance manager, whereasIsManagedByInstance, api/v1/backup_funcs.go:319), volumeSnapshot has the operator take snapshots directly. Instance-side backups select the target pod (either primary or the most advanced standby, depending on thetarget configuration) and exec /controller/manager backup <이름> inside that pod's PostgreSQL container (startInstanceManagerBackup, :968). This command requests a backup from the local web server (requestBackup, pkg/management/postgres/webserver/local.go:131), and if it is a plugin, PluginBackupCommand.invokeStart, webserver/plugin_backup.go:72 calls Backup.Backup via the socket. The sidecar's BackupServiceImplementation.Backup, instance/backup.go:71 executes barman-cloud-backup (the server name argument is likewise configuration.ServerName) and returns the result to the Backup status.

5. Author's Contributions and Related Areas

The author encountered two issues while migrating a CNPG 1.30 cluster that backed up via in-tree barmanObjectStore to the plugin (v0.14.0), and submitted those experiences as two documentation PRs. Both were pending review as of 2026-10-17.

① Where Does serverName Go? — plugin-barman-cloud#1164(Issue #1163). Previous guides instruct moving the in-tree barmanObjectStore section directly to the ObjectStore's spec.configuration . However, if serverName is present there, the ObjectStore CRD rejects it. The rule is defined by a single CEL line in api/v1/objectstore_types.go:61 (!has(self.serverName)), and the message states: "Use the serverName plugin parameter of the Cluster." The plugin reads this value at NewFromCluster, internal/cnpgi/operator/config/config.go:142 .

	serverName := cluster.Name
	for _, plugin := range cluster.Spec.Plugins {
		if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
			if pluginServerName, ok := plugin.Parameters["serverName"]; ok {
				serverName = pluginServerName
			}
		}
	}

Source: plugin-barman-cloud v0.14.0 internal/cnpgi/operator/config/config.go, Apache-2.0

This value is directly embedded into the WAL path in Section 4.4 and the backup path in Section 4.6. In other words, serverName is "the folder name inside the bucket," and if this value changes during migration, the plugin starts writing to a new folderalongside existing backups. External clusters (recovery/replica sources) also default differently: in-tree falls back to the external cluster name (ExternalCluster.GetServerName, cloudnative-pg/api/v1/cluster_funcs.go:403), whereas the plugin falls back to the name of the Cluster currently being created(config.go:163, :173). The PR documented these two differences in the updated guide. The external cluster behavior was verified solely through code comparison and was not re-tested via recovery (unmeasured).

② "no backup section" — plugin-barman-cloud#1166(Issue #1165). If you remove .spec.backup from the Cluster when migrating to the plugin, any Backup or ScheduledBackup without method falls into the second branch of the Section 4.6 quotation above. This happens because the default value of Backup CRD's method is barmanObjectStore (verified via the installed CRD in Section 6). Because this error message was missing from the plugin's troubleshooting section, the cause and fix (method: plugin + pluginConfiguration.name, kubectl cnpg backup -m plugin) were added there.

③ #679 Comments. Regarding reports that WAL archiving failed with exit code 4 on SeaweedFS, I left a note that it could not be reproduced with the same sidecar image (v0.14.0), along with guidance that "exit code 4 is a generic barman error, so check the exception line immediately preceding it in the sidecar logs." Step 5 in Section 4.4 is precisely where that command runs, and the exit code is wrapped in a gRPC error and bubbles up to manager wal-archive .

6. Measurements: Observations from a Small Cluster

2026-10-17. All commands are read-only (kubectl get·logs, executing inside running pods via exec to inspect /procand configuration files cat). App namespaces and cluster names have been masked, and raw data is stored separately.

Installed Versions and Clusters. cnpg-system has one operator (cloudnative-pg:1.30.0) and one plugin (plugin-barman-cloud:v0.14.0) Deployment. There are four Clusters, all running Cluster in healthy stateand PostgreSQL 18.4 images.

Cluster Instance Plugin .spec.backup ObjectStore
App DB Cluster A 2 barman-cloud (isWALArchiver: true) None Present
Auth Service DB Cluster B 2 barman-cloud None Present
Clusters C, D 1, 2 None None None

Plugin Discovery (Section 4.2). The plugin Service labels were cnpg.io/pluginName: barman-cloud.cloudnative-pg.io, with annotations being cnpg.io/pluginPort: 9090 and the names of both server and client certificate Secrets. The operator logs showed Registered plugin occurring 7 times in the past 24 hours. Cluster A's .status.pluginStatus had version 0.14.0and capabilities TYPE_RECONCILER_HOOKS·TYPE_LIFECYCLE_SERVICE· TYPE_INSTANCE_SIDECAR_INJECTION , which matches the Identity response of the operator half in Section 4.5 precisely.

Instance Pods (Sections 4.3 and 4.5). Both pods in Cluster A share the same configuration.

Item Value
initContainers bootstrap-controller(operator image 1.30.0), plugin-barman-cloud(sidecar image v0.14.0, restartPolicy: Always)
containers postgres single
postgres container PID 1 /controller/manager instance run --status-port-tls --log-level=info
postmaster PID 37, parent PID 1. Below it are checkpointer, walwriter, archiver ("last was …66"), walsender, etc.
/plugins Socket file barman-cloud.cloudnative-pg.io one, /proc/net/unix showing 1 waiting, 1 connected

The sidecar was injected into containers rather than initContainers with restartPolicy: Always . This matches what we read in Section 4.5. The debug logs of the plugin Deployment contained the injection patch, and the caller in those logs was internal/cnpgi/operator/lifecycle.go:364 . Since line 364 of the same file in the v0.14.0 tag corresponds directly to that "generated patch" log line, it served as a bonus confirmation that the running build and the inspected source matched. The patch content was a JSON patch adding /spec/volumes emptyDir to plugins , and /spec/initContainers/1 adding the sidecar to

archive_command (Section 4.4). Read the configuration files in PGDATA.

File Value
custom.conf archive_command = '/controller/manager wal-archive --log-destination /controller/log/postgres.json %p'
custom.conf archive_mode = 'on'
override.conf restore_command = '/controller/manager wal-restore --log-destination /controller/log/postgres.json %f %p'

Cluster configuration archive_timeout is 5 minutes. Cluster C, which has neither backups nor plugins, also had the exact same custom.conf and archive_command in its archive_mode = 'on' . Per step 3 of Section 4.4, those WALs go nowhere and terminate with "Success".

WAL Archive Logs. In the sidecar logs over the past 24 hours Archived WAL file This was 322. If WAL is forcibly rotated every 5 minutes, that amounts to 288 per day, so the remainder appears to be fragments filled by actual writes. The elapsed times for the most recent four fragments (UTC 16:06~16:21, 5-minute intervals) (elapsedWalTime) were 0.237~0.256 seconds. In front of each line, Executing barman-cloud-wal-archive and the argument list (--gzip, --endpoint-url <가림>, s3://<버킷>/, server name) are printed. In contrast, in the postgres container logs, there were 0 lines containing wal-archive over the same 24-hour period. Successful wal-archive leaves nothing behind at the info level, so to view WAL archives, you must check the sidecar logs.

Backups (Section 4.6). There are two ScheduledBackups, both recording method: plugin and pluginConfiguration.name . Reading the installed CRDs, the default value for Backup's spec.method was indeed barmanObjectStore , and ObjectStore CRD's spec.configuration contained the !has(self.serverName) rules as-is (the basis for the two PRs in Section 5).

Cluster Backup Count Result Notes
A 31 (09-16 ~ 10-16, daily) all completed Recent one: started at 03:30:00, ended at 03:33:40 (approx. 3 min 40 sec)
B 28 (1 initial manual + 27 daily) completed 26, failed 2 10-06 and 10-07 failed: rpc error: code = Unknown desc = exit status 1

The failure message for B is precisely the "barman CLI exit code wrapped in a gRPC error string" mentioned at the end of Section 4.4. The root cause itself was not pursued in this post (unverified).

Status is in two places. Cluster A's .status.firstRecoverabilityPoint and .status.lastSuccessfulBackup were stuck at 2026-08-23 . This is the last day it backed up via in-tree. Since this field is annotated in the API types as "Deprecated: Not set for backup plugins", it has not been updated since migrating to the plugin. The current values reside on the ObjectStore side.

Where First Recoverable Point Last Successful Backup
Cluster .status(Value during in-tree era) 2026-08-23 07:25 2026-08-23 07:32
ObjectStore .status.serverRecoveryWindow 2026-09-16 03:33 2026-10-16 03:33

Since the retention policy is 30 days, the first recovery point on the ObjectStore side is cut off at one month ago. If alerting is watching the Cluster-side fields, it will quietly halt after the migration.

There were no connection leaks. Noting that four places, including archiveWALViaPlugins in Section 4.4, have code that creates and closes an extra unused plugin repository (Section 8), we checked whether actual client-side connection pools accumulated without closing. On the primary pod, which backed up daily for 26 days, /proc/net/unix 's plugin socket had only 1 idle and 1 active connection. There are no traces of leaks.

7. Where to Read First

  1. cnpg-i/proto/identity.proto and wal.proto. Looking at the contract first makes the code on both sides easy to read.
  2. cnpg-i-machinery pkg/pluginhelper/http/server.go:152. See how the plugin opens the server (TCP vs. socket).
  3. plugin-barman-cloud internal/cnpgi/operator/lifecycle.go:88 and common/wal.go:107. What the two halves do respectively.
  4. cloudnative-pg internal/controller/plugin_controller.go:135 → internal/cnpi/plugin/connection/connection.go:442. Where the operator discovers plugins and reads capabilities.
  5. pkg/management/postgres/archiver/archiver.go:156. Where the in-tree and plugin paths diverge in a single function.
  6. internal/controller/cluster_controller.go:310. Finally, reading the large loop shows how the pieces seen earlier fit together.

8. Good First Contributions

Things actually noticed while reading the source code. They haven't been posted anywhere yet, and existing issues should be checked before posting.

Both repositories' CONTRIBUTING files point to the CloudNativePG common contribution guidelines (code of conduct, AI usage, workflow). If AI assistance was used, stating it with a Assisted-by trailer in commits is this project's convention. As of 2026-10-17, issues opened with the good first issue label were 2 in the main repository and 0 in the plugin repository.

9. Limitations

Titi's Word. PostgreSQL writes letters only inside the house, and once placed in the mailbox (socket), the next-door delivery person (sidecar) takes them out. The address written on the envelope is precisely the serverName, so if you miswrite the address when moving, a new mailbox gets created right next to your old one!

References

All materials were accessed on 2026-10-17.

Quoted code belongs to cloudnative-pg and plugin-barman-cloud, both repositories under Apache License 2.0.

Sign in to like

Comments

No comments yet.

Sign in to leave a comment