Утилита резервирования pgBackRest перестала поддерживаться, стало актуальным найти ей замену. Главными альтернативами называют WAL-G и Barman. Можно использовать pg_basebackup+pg_receivewal. Преимущество WAL-G в том, что резервирование возможно по протоколу S3, WAL-G обеспечивает более высокую скорость резервирования и сжатия, имеет неплохие перспективы развития. Кроме протокола S3, WAL-G может резервировать и восстанавливать из директории в файловой системе, работает с Patroni. Директория не обязательно находится на локальном диске, можно смонтировать любую файловую систему, например, NFS. Утилита свободно распространяемая.
В статье рассматриваются примеры команд, которыми можно резервировать и восстанавливать PostgreSQL утилитой WAL-G с защитой от потери транзакций (zero data loss).


WAL-G можно собрать из исходников или из установить из пакета. Инсталляционный пакет содержит единственный файл wal-g, который будет распакован в директорию. Чтобы не писать каждый раз путь к утилите, можно создать символическую ссылку в директории, которая есть в переменной окружения $PATH:
root@host:~$ dpkg -i wal-g-*.deb root@host:~$ ln -s /opt/tantor/usr/bin/wal-g /usr/local/bin/wal-g
Настройки утилиты хранятся в одном файле. По умолчанию, местоположение файла параметров $HOME/.walg.json Можно иметь несколько файлов с разными настройками и указывать нужный файл параметром wal-g --config.
Для бэкапа в директорию файловой системы достаточно создать файл:
root@host:~$ su - postgres postgres@host:~$ cat > $HOME/.walg.json << EOF { "WALG_FILE_PREFIX": "/var/lib/postgresql/backup", "WALG_COMPRESSION_METHOD": "brotli", "WALG_DELTA_MAX_STEPS": "5", "PGHOST": "/var/run/postgresql", "PGDATA": "/var/lib/postgresql/tantor-se-server-18/data" } EOF
Резервирование будет выполняться в директорию, на которую указывает WALG_FILE_PREFIX.
Скрытый текст
Пример файла конфигурации для протокола S3:
postgres@host:~$ cat > .walg.json << EOF { "AWS_ENDPOINT": "http://127.0.0.1:9000", "WALG_S3_PREFIX": "s3://bucket1", "AWS_ACCESS_KEY_ID": "rustfsadmin", "AWS_SECRET_ACCESS_KEY": "rustfsadmin", "AWS_S3_FORCE_PATH_STYLE": "true", "WALG_COMPRESSION_METHOD": "brotli", "WALG_DELTA_MAX_STEPS": "5", "PGDATA": "/var/lib/postgresql/tantor-se-18/data", "PGHOST": "/var/run/postgresql" } EOF
Пример установки S3-сервера, чтобы попробовать работу WAL-G по протоколу S3:
root@host:~$ curl -O https://rustfs.com/install_rustfs.sh && bash install_rustfs.sh Service port: 9000, Console port: 9001, Data directory: /data/rustfs0 root@host:~$ mkdir /data/rustfs0/bucket1
У S3-сервера есть веб-консоль управления http://localhost:9001 (rustfsadmin/rustfsadmin)
Приведённые в статье примеры можно попробовать на виртуальной машине Tantor DBA1-18.ova

Алгоритм brotli обеспечивает лучшее и быстрое сжатие (лучше чем LZ4, быстрее чем LZMA). Благодаря нему и многопоточности, WAL-G чрезвычайно быстро резервирует.
Для работы не с директорией, а по протоколу S3 достаточно поменять параметры в файле $HOME/.walg.json, команды резервирования и восстановления остаются теми же самыми. Или создать ещё один файл и добавить параметр --config к параметрам утилиты WAL-G.
Для проверки того, что wal-g может работать с настройками в файле, можно дать команду:
postgres@host:~$ wal-g backup-list INFO: 2026/04/28 10:33:54.281318 List backups from storages: [default] INFO: 2026/04/28 10:33:54.281702 No backups found
Команда не выдала ошибки, значит, файл параметров корректный. Бэкапов нет, так как мы их ещё не делали.
Конфигурирование PostgreSQL для архивирования WAL
Чтобы с бэкапа можно было полностью восстановиться, нужно сохранять все WAL-файлы с начала бэкапа до самого последнего. WAL файлы можно вытягивать по протоколу репликации или передавать командой, указанной в параметре конфигурации archive_command (текущий WAL-файл команда не может передать). Для передачи WAL-файлов утилитой WAL-G в архив достаточно установить параметры:
postgres=# alter system set archive_command = 'wal-g wal-push "%p" >> $PGDATA/log/archive_command.log 2>&1'; alter system set restore_command = 'wal-g wal-fetch "%f" "%p" >> $PGDATA/log/restore_command.log 2>&1'; alter system set archive_mode=on;
Параметр archive_command задаёт команду, которая будет выполняться после переключения на следующий WAL-файл («сегмент»). %p - переменная, которая инициализируется названием и путём к WAL-файлу, в который завершена запись и который должен быть передан в архив.
Параметр restore_command указывает, какая команда будет выполнена процессом startup, который восстанавливает кластер после запуска экземпляра и определяет по файлу backup_label или pg_control, какой WAL-сегмент нужен для продолжения восстановления (будет накатываться следующим). Эта команда должна создать WAL-файл в директории $PGDATA/pg_wal.
Параметр archive_mode включает действие параметра archive_command.
WAL-G и pg_receivewal
WAL-G можно совместить с pg_receivewal, получив преимущества высокоскоростного создания сжатых бэкапов, которые делает WAL-G и отсутствие потерь транзакций (zero data loss), которое обеспечивает pg_receivewal. При использовании pg_receivewal нужно задать в параметре restore_command команду копирования из директории, куда утилита pg_receivewal вытягивала журналы. Пример команды запуска pg_receivewal:
postgres@host:~$ rm -rf $HOME/archivelog mkdir $HOME/archivelog psql -c "alter system set max_slot_wal_keep_size = '1TB';" psql -c "select pg_reload_conf();" pg_receivewal --drop-slot --slot=arch pg_receivewal --create-slot --slot=arch pg_receivewal -D $HOME/archivelog --slot=arch --synchronous
Утилиту pg_receivewal можно запускать как службу через systemd (так же как и экземпляр PostgreSQL). Если нужна гарантия отсутствия потерь транзакций, то нужно задать параметр конфигурации synchronous_standby_names=pg_receivewal, тогда транзакции будут подтверждаться только после того, как pg_receivewal получит запись о фиксации транзакции (и все предыдущие журнальные записи) и сохранит её в файле .partial. Однако, команды фиксации транзакций могут выполняться с большей задержкой.
Малоизвестно, но это важно: чтобы файл *.partial применялся при запуске экземпляра, нужно использовать следующее значение для параметра конфигурации restore_command:
alter system set restore_command = 'wal-g wal-fetch "%f" "%p" >> $PGDATA/log/restore_command.log 2>&1 || cp $HOME/archivelog/%f %p || cp $HOME/archivelog/%f.partial %p';
Файлы с расширением .partial не применяются при восстановлении. Без применения этого файла последние транзакции будут потеряны. Чтобы файл .partial применился, важно убрать расширение у файла, что учтено в вышеприведённой команде. Первая часть команды восстанавливает журнал, заархивированный WAL-G. Если в архиве его нет, то журнал копируется из архива pg_receivewal. Если такого файла нет, то копируется файл .partial (в котором и находятся самые последние изменения) и убирается расширение у файла.
Стоит протестировать, применяется ли (накатывается) в ваших скриптах и утилитах восстановления файл .partial. В документации к Barman о файле .partial, хоть и излишне сложно, но написано. Более просто про файл .partial написал Лоренц Альбе. В Barman предлагается вручную копировать и переименовывать файл, но это плохо тем, что при сбоях лучше минимизировать ручное вмешательство, так как от волнения вероятность ошибиться возрастает. При использовании WAL-G копирование и переименование файла .partial заранее автоматизируется в restore_command.
Скрытый текст
На языке Go написан аналог pg_receivewal, который называется pgrwl. Он работает с S3 и файловой системой, но с файлом .partial работает точно так же, как pg_receivewal. Так как pg_receivewal входит в стандартную поставку и поддерживается сообществом, то имеет смысл использовать pg_receivewal.
Push или Pull
Альтернатива архивированию с помощью параметров archive_* ("push") - запустить wal-g как службу, чтобы она получала ("pull") файлы журналов:
postgres@host:~$ wal-g wal-receive INFO: 2026/04/28 21:44:41.565679 FILE PATH: 00000002.history.
При использовании этого способа архивирования WAL, нужно установить только параметр restore_command, параметр archive_mode нужно вернуть к значению по умолчанию (off). Поскольку, даже в этом режиме, WAL-G принимает только сформированные WAL-файлы, то с WAL-G проще использовать archive_command, а не режим “pull”. Единственно, надо проследить за тем, чтобы с резервируемого хоста нельзя было стирать или менять файлы в директории, куда резервируются файлы, иначе злоумышленник, завладевший резервируемым хостом, сможет стереть или испортить бэкапы.
WAL-G может не только вытягивать журналы, но и резервировать кластер PostgreSQL (PGDATA) в режиме “pull”, используя репликационный протокол. Эта возможность уже готова и будет включена в следующую версию WAL-G. При использовании репликационного протокола пока нет многопоточной передачи и дельта-бэкапов и бэкап кластера будет создаваться дольше. Это касается только создания бэкапов в режие «pull», вытягивание WAL не имеет таких ограничений. Также, ни в режиме «push», ни в режиме «pull» WAL-G не принимает текущий файл WAL и при полной потере директории PGDATA/pg_wal нельзя будет восстановить транзакции из текущего файла WAL. Это не является проблемой, так как WAL-G может архивировать и восстанавливать журналы совместно с утилитой pg_receivewal.
Отсутствие потерь (zero data loss, RPO=0) способны обеспечить: утилита pg_receivewal, процесс walreceiver (на физических репликах), Polar DataMax (в Tantor XData).
Создание бэкапа утилитой WAL-G
Чтобы изменения подействовали, нужно остановить и запустить (перезапустить недостаточно) экземпляр.
Переключимся на новый WAL-сегмент, так как archive_command выполняется только после завершения записи в WAL-файл процессами экземпляра и переключения на следующий:
postgres@host:~$ psql -c "select pg_switch_wal();" pg_switch_wal --------------- 0/30002BC (1 row) postgres@host:~$ cat $PGDATA/log/archive_command.log INFO: 2026/04/28 11:31:34.145668 Files will be uploaded to storage: default INFO: 2026/04/28 11:31:34.192862 FILE PATH: 000000010000000000000003.br
Появился файл archive_command.log, путь к которому был указан в параметре archive_command.
Зарезервируем директорию кластера. Первый бэкап всегда полный, от него отсчитываются «дельты» (дифференциальные инкрементальные бэкапы). В команде создания бэкапа нужно передать название директории кластера:
postgres@host:~$ wal-g backup-push $PGDATA INFO: 2026/04/28 11:40:37.903727 Backup will be pushed to storage: default INFO: 2026/04/28 11:40:37.912409 Couldn't find previous backup. Doing full backup. ... INFO: 2026/04/28 11:40:38.357616 Wrote backup with name base_000000010000000000000005 to storage default
Проверка, что созданный бэкап есть в списке:
postgres@host:~$ wal-g backup-list INFO: 2026/04/28 11:47:02.111831 List backups from storages: [default] backup_name modified wal_file_name storage_name base_000000010000000000000005 2026-04-28T11:40:38+03:00 000000010000000000000005 default
В директории для бэкапов /var/lib/postgresql/backup появятся файлы, которые и являются бэкапом кластера баз данных:
postgres@host:~$ ls -al $HOME/backup/basebackups_005/*/tar_partitions total 2760 -rw-r--r-- 1 postgres postgres 269 Apr 28 11:40 backup_label.tar.br -rw-r--r-- 1 postgres postgres 2806055 Apr 28 11:40 part_001.tar.br -rw-r--r-- 1 postgres postgres 300 Apr 28 11:40 pg_control.tar.br
Следующие пять (WALG_DELTA_MAX_STEPS) бэкапов будут сделаны в режиме DELTA:
postgres@host:~$ wal-g backup-push $PGDATA INFO: 2026/04/28 11:59:41.614186 Backup will be pushed to storage: default INFO: 2026/04/28 11:59:41.628244 LATEST backup is: 'base_000000010000000000000005' INFO: 2026/04/28 11:59:41.629001 Delta backup from base_000000010000000000000005 with LSN 0/5000028. ... INFO: 2026/04/28 11:59:41.833147 Wrote backup with name base_000000010000000000000007_D_000000010000000000000005 to storage default
Полезна команда удаления мусора в архиве - неудачные бэкапы, ненужные журнальные файлы:
postgres@host:~$ wal-g delete garbage --confirm INFO: 2026/04/28 20:49:20.660407 Backup to delete will be searched in storages: [default] INFO: 2026/04/28 20:49:20.660540 retrieving permanent objects INFO: 2026/04/28 20:49:20.661749 Running in default mode. Will remove outdated WAL files and leftover backup files. INFO: 2026/04/28 20:49:20.662257 Start delete INFO: 2026/04/28 20:49:20.663400 Objects in folder: INFO: 2026/04/28 20:49:20.663440 will be deleted: wal_005/00000002000000000000002A.br, from storage: default
Если WAL-файлы вытягиваются утилитой pg_receivewal, то после создания бэкапа изменится файл $PGDATA/pg_wal/*.backup. После архивирования командой в параметре archive_command создаются файлы $PGDATA/pg_wal/archive_status/*000000??.done. Имена этих файлов можно использовать для удаления WAL-файлов, которые вытягивает pg_receivewal. Пример команды удаления файлов, созданных pg_receivewal, если они уже заархивированы:
pg_archivecleanup $HOME/archivelog $(basename $(ls $PGDATA/pg_wal/archive_status/*000000??.done | sort -r | head -n 1) .done)
Скрытый текст
Для примера, команда для удаления файлов, которые не нужны последнему бэкапу:
pg_archivecleanup $HOME/archivelog $(basename $(ls $PGDATA/pg_wal/*.backup))
Команду pg_archivecleanup можно запускать по расписанию с желаемой частотой, которую выбрать исходя из объема генерируемых WAL и свободного места в директории (в примере $HOME/archivelog).
Восстановление из бэкапа, созданного WAL-G
Остановим экземпляр и удалим директорию PGDATA:
postgres@host:~$ pg_ctl stop waiting for server to shut down.... done server stopped postgres@host:~$ rm -rf $PGDATA/*
Команда симулирует полную потерю кластера баз данных («disaster»). Команда удаляет, в том числе и текущий WAL-сегмент, который не был записан в архив утилитой WAL-G, но если работала утилита pg_receivewal, то она сохранила записи текущего сегмента в файле .partial. Директория, в которую будет выполняться восстановление из бэкапа должна быть пустой.
Команда восстановления директории кластера из бэкапа:
postgres@host:~$ wal-g backup-fetch $PGDATA LATEST INFO: 2026/04/28 12:56:37.402035 Selecting the latest backup... INFO: 2026/04/28 12:56:37.402219 Backup to fetch will be searched in storages: [default] INFO: 2026/04/28 12:56:37.402360 LATEST backup is: 'base_000000010000000000000007_D_000000010000000000000005' INFO: 2026/04/28 12:56:37.406190 Delta from base_000000010000000000000005 at LSN 0/5000028 ... INFO: 2026/04/28 12:56:38.500783 base_000000010000000000000005 fetched. Upgrading from LSN 0/5000028 to LSN 0/7000028 ... Backup extraction complete.
Директория PGDATA восстановлена. Проверим содержимое директории журналов:
postgres@host:~$ ls $PGDATA/pg_wal
Директория пуста, как и директория с диагностическими файлами PGDATA/log, что нормально, файлы WAL восстанавливаются отдельно командой, указанной в параметре конфигурации restore_command.
Вместо управляющего файла будет использоваться файл backup_label:
postgres@host:~$ cat $PGDATA/backup_label START WAL LOCATION: 0/7000028 (file 000000010000000000000007) CHECKPOINT LOCATION: 0/7000098 BACKUP METHOD: streamed BACKUP FROM: primary START TIME: 2026-04-28 11:59:41 MSK LABEL: 2026-04-28 11:59:41.640728 +0300 MSK m=+0.075156967 START TIMELINE: 1
Нужно создать файл recovery.signal, который укажет, что выполняется восстановление из бэкапа и запустить экземпляр:
postgres@host:~$ touch $PGDATA/recovery.signal postgres@host:~$ pg_ctl start done server started
Процесс startup будет выполнять команду, указанную в параметре конфигурации restore_command и применять WAL-файлы, которые эта команда скопирует в директорию PGDATA/pg_wal. Экземпляр будет переведён в состяние, в соответствии со значениями параметров (recovery_target_*), которыми можно указать, до какого момента выполнять восстановление и что делать после достижения этого момента.
Первая часть restore_command (wal-g wal-fetch “%f” “%p”) вынет из архива WAL-G и накатит журналы вплоть до текущего WAL-сегмента. Если запускался pg_receivewal, то последняя часть restore_command скопирует и накатит файлы, которые не смог скопировать WAL-G (например, из-за временной недоступности S3 хранилища) и файл .partial, который содержит журнальные записи из текущего WAL-сегмента. Журнальные файлы, которые не попали в архивы wal-g и pg_receivewal, не применятся, и транзакции, которые могли бы в них быть, потеряются. Вероятность того, что две утилиты не смогут или не успеют заархивировать WAL файлы мала. Для полной защиты от такой ситуации используется параметр synchronous_standby_names.
После восстановления слоты репликации удалены и, если они используются, то их надо снова создать. Если использовалась утилита pg_receivewal (которую мы не останавливали и она продолжит вытягивать WAL уже с восстановленного кластера), то после восстановления для неё нужно снова создать слот репликации:
postgres@host:~$ pg_receivewal --create-slot --slot=arch
Сравнение WAL-G с Barman есть в комментариях к статье и самой статье.
Заключение
После прекращения развития утилиты pgBackRest, стал актуальным выбор перспективных утилит резервирования. Там, где нужна простота, высокая скорость резервирования и сжатия, WAL‑G неплохой выбор. WAL‑G имеет большое число разработчиков из разных стран и активно развивается. В статье даны примеры, как установить и сконфигурировать WAL-G и команды, которыми можно зарезервировать и восстановить PostgreSQL с гарантией отсутствия потерь транзакций (zero data loss).
bigtrot
В программном средстве barman есть возможность настройки различных политик связанных с ротацией архивов, а также автоматизации самого процесса регулярного архивирования.
Вопрос есть ли такие же возможности в WAL-G. Или это надо еще оборачивать в свой скрипт?
OlegIct Автор
Политики удаления (бэкапов и ненужных оставшимся бэкапам архивов журналов) есть: retain (аналог redundancy), before (аналог recovery window), everything, target. Пример удаления всех бэкапов, кроме двух последних. Команда
wal-g delete retain 2 --confirmпланировщик есть в Платформе Тантор, можно использовать cron.
Можно написать скрипт, можно отдельными командами:
wal-g backup-push $PGDATA -fwal-g delete retain2--confirm