Bidirectional bucket interop is the project's acceptance bar: a bucket
written by wal-g v3.x is listable / fetchable / replayable / verifiable
/ deletable by walrus, and the reverse. CI gates the claim
(ci/cross_tool_{forward,reverse}.sh against a pinned wal-g
version in .github/workflows/pg-compat.yml; bumping the pin is a
deliberate one-line change so an interop-breaking wal-g release fails
the bump PR, not master).
The on-bucket format is wal-g's verbatim, so this doc covers only the
gaps. Matched without further note: key layout 005, the
BackupSentinelDtoV2 sentinel (PascalCase, tolerant-deserialized so
either tool's sentinels parse), files_metadata.json, delta naming
(base_<24hex>_D_<parent_24hex>, chain via sentinel IncrementFrom,
format magic-detected per file), wi1 and PG17 native INCREMENTAL
payloads, libsodium secretstream framing, prefetch dir layout, the
daemon Unix-socket protocol, the delete mode + modifier vocabulary,
and WALG_* / PG* / AWS_* / GOOGLE_* env naming.
Both tools emit byte-identical wi1 / native increments (see above), so a
delta produced by either restores under either. They diverge only in how the
producer decides which blocks an increment carries.
wal-g defaults to a full scan (WALG_USE_WAL_DELTA is false by default): it
reads every page of every paged relation and ships a page only if the page is
new (pd_upper == 0) or its header LSN is at or past the increment-base LSN
(incremental_page_reader.go:SelectNewValidPage, a predicate lifted from
PostgreSQL's own page-validity checks and refined on pgsql-hackers). This is
self-validating: it needs no WAL and re-derives "changed" from each page's own
header, so a gap in the archived WAL cannot silently drop a changed block.
Setting WALG_USE_WAL_DELTA=true switches wal-g to instead trust a WAL-derived
changed-block bitmap (file-size gated, no per-page LSN recheck), warning and
falling back to the full scan when the bitmap can't be loaded
(WALG_FORCE_WAL_DELTA forbids that fallback).
walrus implements only the map-trusting path. classify_for_delta ships
exactly the blocks the changed-block map reports, filtered to blocks within the
current file size, with no page-LSN recheck. The map is built from WAL
<group>_delta sidecars (raw-WAL walk when a sidecar is missing) or from
pg_walsummary under --delta-from-wal-summaries; if it can't be built, walrus
produces a full backup rather than a scan-based delta. So for walrus
WALG_USE_WAL_DELTA only governs sidecar recording during wal-push, not
selection — backup-push always selects blocks from a WAL/summary map regardless
— and a walrus delta is correct only if that map is complete, whereas wal-g's
default would still catch a missed block by its page LSN.
| Area | walrus behavior |
|---|---|
OpenPGP (WALG_PGP_*) |
hard error at startup, never silently plaintext; re-encrypt to libsodium when migrating (see DESIGN.md for rationale) |
wal-receive slot (WALG_SLOTNAME) |
unset/empty runs slotless (no slot created or used); wal-g instead defaults to a walg slot. Slotless avoids pinning primary WAL when the archiver lags or dies (server recycles WAL, archive may gap) at the cost of slot retention; set WALG_SLOTNAME explicitly to opt into a slot |
| Backends | file://, s3://, gs:// only; no azure / oss / swift / sh |
statsd (WALG_STATSD_*) |
not implemented |
| catchup-push / -fetch / -send / -receive / -list | not implemented |
| Windows | non-goal |
| Other databases (mongo, mysql, redis, …) | non-goal, Postgres only |
Compared against wal-g Postgres CommonAllowedSettings,
PGAllowedSettings, storage adapters, and pgx.ParseConfig environment
support. Unsupported means walrus ignores the variable unless noted
otherwise.
walrus parses a subset of libpq-style environment variables. wal-g uses pgx, which accepts more connection variables:
PGPASSFILEPGSERVICEPGSERVICEFILEPGSSLPASSWORDPGOPTIONSPGAPPNAMEPGCONNECT_TIMEOUTPGTARGETSESSIONATTRSPGTZPGMINPROTOCOLVERSIONPGMAXPROTOCOLVERSIONPGSSLSNIPGSSLNEGOTIATIONPGCHANNELBINDINGPGREQUIREAUTH
Partial support:
PGDATA: walrus uses it only for daemon path resolution, not as backup-push data directory config.backup-push <PGDATA>positional syntax matches wal-g CLI behaviorPGHOST,PGPORT: walrus supports single host/port only, not pgx multihost semantics
WALG_UPLOAD_DISK_CONCURRENCYWALG_SENTINEL_USER_DATAWALG_UPLOAD_WAL_METADATAWALG_TAR_DISABLE_FSYNCWALG_DIRECT_IOPG_READY_RENAMEWALG_SLOTNAMEWALG_PG_WAL_SIZEWALG_PG_WAL_PAGE_SIZEWALG_PG_BLOCK_SIZEWALG_ALIVE_CHECK_INTERVALWALG_STOP_BACKUP_TIMEOUTWALG_FORCE_WAL_DELTAWALG_DISABLE_PARTIAL_RESTOREWALG_USE_REVERSE_UNPACKWALG_SKIP_REDUNDANT_TARSWALG_VERIFY_PAGE_CHECKSUMSWALG_STORE_ALL_CORRUPT_BLOCKSWALG_USE_RATING_COMPOSERWALG_USE_COPY_COMPOSERWALG_USE_DATABASE_COMPOSERWALG_WITHOUT_FILES_METADATAWALG_INTEGRITY_MAX_DELAYED_WALSWALG_TARGET_STORAGEPGBACKREST_STANZA
WALG_CONFIG_PATHWALG_STORAGE_PREFIXWALG_LOG_DESTINATIONWALG_STATSD_ADDRESSWALG_STATSD_EXTRA_TAGSPROFILE_SAMPLING_RATIOPROFILE_MODEPROFILE_PATHHTTP_LISTENHTTP_EXPOSE_PPROFHTTP_EXPOSE_EXPVARGOMAXPROCSGODEBUG
Accepted by wal-g Postgres config but not used by PG code paths:
WALG_SERIALIZER_TYPEWALG_STREAM_CREATE_COMMANDWALG_STREAM_RESTORE_COMMAND
WALG_CSE_KMS_IDWALG_CSE_KMS_REGIONYC_CSE_KMS_KEY_IDYC_SERVICE_ACCOUNT_KEY_FILE
WALE_S3_PREFIXAWS_DEFAULT_REGIONAWS_DEFAULT_OUTPUTAWS_PROFILEAWS_SHARED_CREDENTIALS_FILEAWS_CONFIG_FILEAWS_CA_BUNDLEAWS_ROLE_ARNAWS_ROLE_SESSION_NAMEAWS_WEB_IDENTITY_TOKEN_FILEAWS_DUAL_STACKWALG_S3_CA_CERT_FILES3_CA_CERT_FILEWALG_S3_STORAGE_CLASSS3_STORAGE_CLASSWALG_S3_SSES3_SSEWALG_S3_SSE_CS3_SSE_CWALG_S3_SSE_KMS_IDS3_SSE_KMS_IDWALG_S3_MAX_PART_SIZES3_MAX_PART_SIZEWALG_S3_ENDPOINT_SOURCES3_ENDPOINT_SOURCEWALG_S3_ENDPOINT_PORTS3_ENDPOINT_PORTWALG_S3_USE_LIST_OBJECTS_V1S3_USE_LIST_OBJECTS_V1WALG_S3_LOG_LEVELS3_LOG_LEVELWALG_S3_RANGE_BATCH_ENABLEDS3_RANGE_BATCH_ENABLEDWALG_S3_RANGE_MAX_RETRIESS3_RANGE_MAX_RETRIESWALG_S3_MAX_RETRIESS3_MAX_RETRIESS3_SKIP_VALIDATIONS3_USE_YC_SESSION_TOKENUPLOAD_CONCURRENCYS3_REQUEST_ADDITIONAL_HEADERSS3_MIN_THROTTLING_RETRY_DELAYS3_MAX_THROTTLING_RETRY_DELAYS3_RETENTION_PERIODS3_RETENTION_MODES3_DISABLE_100_CONTINUES3_ENABLE_VERSIONINGS3_DELETE_BATCH_SIZE
WALE_GS_PREFIXGCS_CONTEXT_TIMEOUTGCS_NORMALIZE_PREFIXGCS_ENCRYPTION_KEYGCS_MAX_CHUNK_SIZEGCS_MAX_RETRIES
GCE/GKE metadata-server auth is not implemented.
Azure, Alicloud OSS, Swift, and SSH backends are absent (see the
divergence table), so all their env vars (WALG_AZ_PREFIX / AZURE_*,
WALG_OSS_PREFIX / OSS_*, WALG_SWIFT_PREFIX / OS_*,
WALG_SSH_PREFIX / SSH_*), the WALE_FILE_PREFIX file alias, and
failover storages (WALG_FAILOVER_STORAGES*) are unsupported.
wal-g storage adapter settings accept exact backend keys first, then
WALG_<key> and WALE_<key> compatibility variants. walrus does not
implement this generic alias rule, so aliases like
WALG_S3_SKIP_VALIDATION, WALE_S3_SKIP_VALIDATION,
WALG_GCS_MAX_RETRIES, WALE_GCS_MAX_RETRIES,
WALG_OSS_REGION, and WALE_OSS_REGION are unsupported unless
explicitly listed as supported elsewhere in this document.