Companion Reference
This document documents every companion command, flag, and default.
The companion is a single binary built from the companion directory.
Building the companion
Build the binary with the Go toolchain, version 1.25 or later:
cd companion
go build -o volvra-companion .
The companion depends on github.com/jackc/pglogrepl and
github.com/jackc/pgx/v5. Both declare a minimum of Go 1.25, which
sets the floor for the companion. Both are client libraries, so
neither imposes anything on the database.
Command summary
The following table describes each command:
| Command | Purpose |
|---|---|
| run | Stream a replication slot and archive the changes. |
| verify | Re-hash every segment and re-walk the manifest chain. |
| restore | Load an archive back into volvra.change_log. |
| status | Report the durable tier from the database's point of view. |
| help | Print usage. |
Common flags
The following table describes the flags every command accepts:
| Flag | Default | Description |
|---|---|---|
| --dsn | The VOLVRA_DSN environment variable | The libpq connection string. |
| --archive | None | The archive directory. |
Give the connection string as a URL or as keyword and value pairs. Both forms work, because the companion parses the string rather than appending to it.
The companion registers every flag for every command, so a flag that does not apply to a command is accepted and ignored rather than rejected. The tables below group each flag with the command the flag affects.
The run command
run creates the slot if the slot is absent, resumes from the archive,
and streams until interrupted:
volvra-companion run --dsn "$DATABASE_URL" \
--archive /srv/volvra-archive \
--slot volvra_companion \
--publication volvra_pub \
--segment-bytes 67108864 \
--lag-warn 536870912 \
--lag-max 5368709120
The following table describes each flag the command accepts:
| Flag | Default | Description |
|---|---|---|
| --slot | volvra_companion | The logical replication slot to read. |
| --publication | volvra_pub | The publication to stream. |
| --segment-bytes | 67108864, which is 64 MB | Rotate to a new segment once the current one reaches this size. |
| --lag-warn | 536870912, which is 512 MB | Log a warning once the slot retains this much write-ahead log. |
| --lag-max | 5368709120, which is 5 GB | Advance the slot past this volume and record the skipped range as a gap. |
The command requires --dsn and --archive.
How run acknowledges progress
The companion tells PostgreSQL that write-ahead log may be discarded only up to a position the companion has written, flushed, and recorded in the manifest. Acknowledging sooner would let PostgreSQL discard log the archive does not hold.
The archive is therefore the authority on what is durable, rather than the slot. On start, the companion resumes from the last position the archive holds, even when the slot has confirmed a later position.
The verify command
verify checks an archive with no database connection:
volvra-companion verify --archive /srv/volvra-archive
The command prints the archive path, the slot, the segment count, and the change count, then either confirms the archive or lists one finding per problem segment. The command exits non-zero when any finding is present.
The restore command
restore verifies the archive, then loads the changes:
volvra-companion restore --archive /srv/volvra-archive \
--dsn "$DATABASE_URL"
The following table describes the flag the command adds:
| Flag | Default | Description |
|---|---|---|
| --dry-run | Off | Parse and count without connecting to a database or changing anything. |
The command refuses an archive that does not verify. Gap and truncate records carry no row image, so the command reports those as skipped.
Restored rows carry actor set to archive: followed by the log
position, and db_user set to archive, so restored history is
distinguishable from history the trigger tier captured.
The status command
status reports the durable tier as the database sees it:
volvra-companion status --dsn "$DATABASE_URL"
The command calls volvra.companion_status, so the output matches
what that function returns in SQL.
The archive on disk
An archive directory holds a manifest and one file per segment. The following table describes the contents:
| Path | Contents |
|---|---|
| manifest.json | Archive metadata and one record per sealed segment. |
| 0000000001.ndjson | The first segment, one JSON change per line. |
The following table describes each field of a segment record in the manifest:
| Field | Meaning |
|---|---|
| seq | Segment number. |
| file | Segment file name. |
| start_lsn | Log position of the first change in the segment. |
| end_lsn | Log position of the last change in the segment. |
| changes | Number of lines in the segment. |
| bytes | Size of the segment in bytes. |
| sha256 | Hash of the segment content. |
| prev | Chain value of the previous segment. |
| chain | Hash of the previous chain value and this segment's hash. |
| sealed_at | When the companion closed the segment. |
The following table describes the top-level manifest fields:
| Field | Meaning |
|---|---|
| archive | Always the string volvra. |
| format | Archive format version. |
| slot | Replication slot the archive belongs to. |
| publication | Publication the companion streamed. |
| created_at | When the archive was first opened. |
| segments | The array of segment records described above. |
The companion refuses to append to an archive whose slot differs from the one given on the command line, so two slots cannot be mixed into one archive.
Change records
The following table describes each field of a change record:
| Field | Meaning |
|---|---|
| lsn | Log position of the change. |
| xid | Transaction identifier. |
| commit_ts | Commit timestamp of the transaction. |
| table | Schema-qualified table name, with every identifier quoted. |
| op | I for insert, U for update, D for delete, T for truncate. |
| pk | Primary key of the affected row. |
| old | Column values before the change. |
| new | Column values after the change. |
A gap record replaces the row fields with the following:
| Field | Meaning |
|---|---|
| gap | Always true. |
| from_lsn | Start of the range the companion could not archive. |
| to_lsn | End of that range. |
| reason | Why the range is missing. |
Exit codes
The following table describes the exit codes:
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | An error occurred; the message names the cause. |
| 2 | The command line was invalid or unrecognized. |
Removing a companion
Stop the companion, then drop the slot so the database stops retaining write-ahead log:
SELECT pg_drop_replication_slot('volvra_companion');
DROP PUBLICATION volvra_pub;
Dropping the slot is the important step. A slot with no consumer retains log indefinitely.
Next Steps
- The Companion Overview document explains what the companion is for.
- The Troubleshooting document covers slot and replication problems.