{"id":46203,"date":"2026-08-04T00:13:44","date_gmt":"2026-08-03T22:13:44","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=46203"},"modified":"2026-08-04T00:33:44","modified_gmt":"2026-08-03T22:33:44","slug":"postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/","title":{"rendered":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In the blog series I previously wrote, I did not answer all the customer&#8217;s questions. The last one was the following:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Can this also be applied to PostgreSQL? <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In short, yes, it is possible. Let&#8217;s see how.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the list of the previous blog posts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs\/\">https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs-2-3\/\">https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs-2-3\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs-rest-api-with-sql-server-2025-3-3\/\">https:\/\/www.dbi-services.com\/blog\/sql-server-snapshot-backup-and-restore-with-proxmox-zfs-rest-api-with-sql-server-2025-3-3\/<\/a><\/li>\n<\/ul>\n\n\n\n<h2 id=\"h-partitioning-and-filesystem\" class=\"wp-block-heading\">Partitioning and filesystem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We will reuse the sqlpool ZFS pool created in the first part of this series.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"134\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-1024x134.png\" alt=\"\" class=\"wp-image-46207\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-1024x134.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-300x39.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-768x100.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1.png 1187w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We identify the 300 GB disk attached to the VM. In our case, it is \/dev\/sdb, backed by the sqlpool\/pve\/vm-307-disk-0 zvol on the Proxmox side:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lsblk<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We create a single partition of type Linux filesystem:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo sgdisk -n 1:0:0 -t 1:8300 \/dev\/sdb<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"458\" height=\"48\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-2.png\" alt=\"\" class=\"wp-image-46208\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-2.png 458w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-2-300x31.png 300w\" sizes=\"auto, (max-width: 458px) 100vw, 458px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We format the partition with XFS, which is the most commonly recommended filesystem for PostgreSQL data directories:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkfs.xfs -L pgdata \/dev\/sdb1 -f<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"208\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-3.png\" alt=\"\" class=\"wp-image-46209\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-3.png 643w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-3-300x97.png 300w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We verify the result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo blkid \/dev\/sdb1<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"32\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-4-1024x32.png\" alt=\"\" class=\"wp-image-46210\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-4-1024x32.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-4-300x9.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-4-768x24.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-4.png 1161w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 id=\"h-\" class=\"wp-block-heading\"><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Mountpoint:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We create the mount point:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/pgdata<\/code><\/pre>\n\n\n\n<h3 id=\"h-\" class=\"wp-block-heading\"><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Persistent mount via fstab<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We add the mount entry to \/etc\/fstab using the filesystem label rather than the device name. The device name (\/dev\/sdb) may change if disks are added or removed while the label remains stable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo 'LABEL=pgdata \/pgdata xfs noatime,nodiratime 0 2' | sudo tee -a \/etc\/fstab\nsudo systemctl daemon-reload\nsudo mount \/pgdata<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"763\" height=\"68\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-5.png\" alt=\"\" class=\"wp-image-46211\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-5.png 763w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-5-300x27.png 300w\" sizes=\"auto, (max-width: 763px) 100vw, 763px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We verify that the volume is mounted:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>df -h \/pgdata<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"402\" height=\"48\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-6.png\" alt=\"\" class=\"wp-image-46212\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-6.png 402w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-6-300x36.png 300w\" sizes=\"auto, (max-width: 402px) 100vw, 402px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">PostgreSQL installation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We install PostgreSQL 18 from the official PGDG repository, which provides the latest PostgreSQL versions for Ubuntu:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y postgresql-common\nsudo \/usr\/share\/postgresql-common\/pgdg\/apt.postgresql.org.sh -y\nsudo apt install -y postgresql-18<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Cluster creation on \/pgdata<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Ubuntu packages create a default cluster under \/var\/lib\/postgresql. This is not what we want. The data files and the WAL must both reside on the ZFS-backed volume, so that a single ZFS snapshot captures a consistent state of the database. If they were on different volumes, the snapshot would not be atomic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We drop the default cluster and recreate it on \/pgdata:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo pg_dropcluster --stop 18 main\nsudo install -d -o postgres -g postgres -m 700 \/pgdata\/18\nsudo pg_createcluster -d \/pgdata\/18\/main 18 main\nsudo systemctl enable --now postgresql@18-main<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"433\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-7-1024x433.png\" alt=\"\" class=\"wp-image-46213\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-7-1024x433.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-7-300x127.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-7-768x325.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-7.png 1076w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We verify that the cluster is online and located on the right volume:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pg_lsclusters\nsudo -u postgres psql -c \"SHOW data_directory;\"\nsudo -u postgres psql -c \"SELECT version();\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"224\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-8-1024x224.png\" alt=\"\" class=\"wp-image-46214\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-8-1024x224.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-8-300x66.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-8-768x168.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-8.png 1064w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We can also confirm that the WAL directory lives inside the data directory, and therefore on the zvol:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -ld \/pgdata\/18\/main\/pg_wal<\/code><\/pre>\n\n\n\n<h2 id=\"h-creating-a-large-database\" class=\"wp-block-heading\">Creating a large database<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We need a database large enough to make traditional backup and restore operations time-consuming. In the SQL Server part of this series, we used the StackOverflow database (about 207 GB). For PostgreSQL, we use pgbench, the benchmarking tool shipped with PostgreSQL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We create the database and initialize it with a scale factor of 10000. This produces a database of approximately 146 GB, with 1 billion rows in the pgbench_accounts table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres createdb bench\nsudo -u postgres pgbench -i -s 10000 --partitions=8 bench<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"806\" height=\"195\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-9.png\" alt=\"\" class=\"wp-image-46215\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-9.png 806w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-9-300x73.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-9-768x186.png 768w\" sizes=\"auto, (max-width: 806px) 100vw, 806px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A few minutes later:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"825\" height=\"88\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-10.png\" alt=\"\" class=\"wp-image-46216\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-10.png 825w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-10-300x32.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-10-768x82.png 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We can monitor the data growth during the initialization:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>watch -n 30 'df -h \/pgdata'<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"663\" height=\"85\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-11.png\" alt=\"\" class=\"wp-image-46217\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-11.png 663w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-11-300x38.png 300w\" sizes=\"auto, (max-width: 663px) 100vw, 663px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A few minutes later:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"463\" height=\"81\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-12.png\" alt=\"\" class=\"wp-image-46218\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-12.png 463w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-12-300x52.png 300w\" sizes=\"auto, (max-width: 463px) 100vw, 463px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">On the Proxmox side:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"292\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-13-1024x292.png\" alt=\"\" class=\"wp-image-46219\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-13-1024x292.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-13-300x86.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-13-768x219.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-13.png 1103w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">After some time, the process completes:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"105\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-14-1024x105.png\" alt=\"\" class=\"wp-image-46220\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-14-1024x105.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-14-300x31.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-14-768x79.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-14.png 1064w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We check the database size:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"786\" height=\"109\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-15.png\" alt=\"\" class=\"wp-image-46221\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-15.png 786w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-15-300x42.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-15-768x107.png 768w\" sizes=\"auto, (max-width: 786px) 100vw, 786px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We run a checkpoint before taking the snapshot. The recovery process starts replaying the WAL from the last checkpoint. By running it right before the snapshot, almost nothing needs to be replayed when the database starts after a restore:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres psql -c \"CHECKPOINT;\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"408\" height=\"36\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-16.png\" alt=\"\" class=\"wp-image-46222\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-16.png 408w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-16-300x26.png 300w\" sizes=\"auto, (max-width: 408px) 100vw, 408px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Comparison with SQL Server<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On the SQL Server side, we had to run SUSPEND_FOR_SNAPSHOT_BACKUP and BACKUP WITH METADATA_ONLY. On the PostgreSQL side, none of that is needed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The data files and the WAL are on the same zvol. An atomic ZFS snapshot therefore captures a state equivalent to a power loss, and PostgreSQL is designed to recover cleanly from that state through crash recovery: the WAL is replayed from the last checkpoint. This is documented and officially supported.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The snapshot is the backup. There is no .bkm file, no metadata backup.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><\/td><td><strong>SQL Server<\/strong><\/td><td><strong>PostgreSQL<\/strong><\/td><\/tr><tr><td><strong>Before the snapshot<\/strong><\/td><td>ALTER DATABASE&#8230;SET SUSPEND_FOR_SNAPSHOT_BACKUP = ON<\/td><td>CHECKPOINT (optional)<\/td><\/tr><tr><td><strong>Backup record<\/strong><\/td><td>BACKUP WITH METADATA_ONLY<\/td><td>None<\/td><\/tr><tr><td><strong>During the restore<\/strong><\/td><td>RESTORE WITH METADATA_ONLY<\/td><td>Automatic crash recovery (WAL replay)<\/td><\/tr><tr><td><strong>Evidence in the logs<\/strong><\/td><td>&#8220;I\/O is frozen&#8221; in the ERRORLOG<\/td><td>&#8220;redo starts\/redo done&#8221; in the PostgreSQL log<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Snapshot process flow<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On the Proxmox side, we create the snapshot and protect it with a hold:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SNAP=\"sqlpool\/pve\/vm-307-disk-0@pg_bench_$(date +%Y%m%dT%H%M%S)\" \nzfs snapshot \"$SNAP\" \nzfs hold sqlsnap \"$SNAP\" \necho \"$SNAP\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The hold protects the snapshot from an accidental destruction, as we did in part 2 of this series. We note the exact snapshot name, it will be needed for the restore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The database stays online during the whole operation. No I\/O freeze is required.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We list the snapshots:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zfs list -t snapshot -r sqlpool\/pve\/vm-307-disk-0<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"707\" height=\"108\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-17.png\" alt=\"\" class=\"wp-image-46223\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-17.png 707w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-17-300x46.png 300w\" sizes=\"auto, (max-width: 707px) 100vw, 707px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We drop the database then we restore the snapshot:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"272\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-18-1024x272.png\" alt=\"\" class=\"wp-image-46224\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-18-1024x272.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-18-300x80.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-18-768x204.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-18.png 1048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We run the snapshot restore procedure. On the VM, we stop the cluster and unmount the volume:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl stop postgresql@18-main\nsudo umount \/pgdata\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On the Proxmox side, we want to restore our snapshot. We can list the available snapshots:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zfs list -t snapshot -r sqlpool\/pve\/vm-307-disk-0<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"690\" height=\"68\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-19.png\" alt=\"\" class=\"wp-image-46225\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-19.png 690w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-19-300x30.png 300w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We roll back the snapshot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zfs rollback -r sqlpool\/pve\/vm-307-disk-0@pg_bench_20260803T165409<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On the VM, we mount the volume and start the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mount \/pgdata\nsudo systemctl start postgresql@18-main<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"439\" height=\"36\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-20.png\" alt=\"\" class=\"wp-image-46226\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-20.png 439w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-20-300x25.png 300w\" sizes=\"auto, (max-width: 439px) 100vw, 439px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We check a few elements in the logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tail -30 \/var\/log\/postgresql\/postgresql-18-main.log<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The service shutdown, then the restart:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"66\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-21-1024x66.png\" alt=\"\" class=\"wp-image-46227\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-21-1024x66.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-21-300x19.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-21-768x49.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-21.png 1290w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">PostgreSQL detects that the database was not shut down properly and replays the WAL. This is the same crash recovery mechanism as in SQL Server. Finally, the database starts.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"90\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-22-1024x90.png\" alt=\"\" class=\"wp-image-46228\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-22-1024x90.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-22-300x26.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-22-768x67.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-22.png 1480w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We then verify that the database is available again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres psql -d bench -c \"SELECT pg_size_pretty(pg_database_size('bench'));\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"696\" height=\"88\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-23.png\" alt=\"\" class=\"wp-image-46229\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-23.png 696w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-23-300x38.png 300w\" sizes=\"auto, (max-width: 696px) 100vw, 696px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Consistency proof under load<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The previous test was done on a quiesced database: we ran a CHECKPOINT right before the snapshot, and nothing was writing. The real question is: what happens if the snapshot is taken while the database is being written to?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is where PostgreSQL differs the most from SQL Server. There is no SUSPEND_FOR_SNAPSHOT_BACKUP. We take the snapshot in the middle of the write activity and we let the WAL replay do the work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We start the load. The built-in pgbench script runs a TPC-B-like transaction: three UPDATE statements on the accounts, tellers and branches tables and one INSERT into the history table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres pgbench -c 8 -j 4 -T 300 bench &amp;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"537\" height=\"81\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-24.png\" alt=\"\" class=\"wp-image-46230\" style=\"width:537px;height:auto\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-24.png 537w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-24-300x45.png 300w\" sizes=\"auto, (max-width: 537px) 100vw, 537px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">While the load is running, we take a snapshot on the Proxmox side:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zfs snapshot sqlpool\/pve\/vm-307-disk-0@pg_bench_$(date +%Y%m%dT%H%M%S)\n\nzfs hold sqlsnap sqlpool\/pve\/vm-307-disk-0@pg_bench_20260803T224551<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"717\" height=\"113\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-25.png\" alt=\"\" class=\"wp-image-46231\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-25.png 717w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-25-300x47.png 300w\" sizes=\"auto, (max-width: 717px) 100vw, 717px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">No CHECKPOINT this time, no freeze. The database is actively writing while the snapshot is taken.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The state after some time under load:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"687\" height=\"187\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-26.png\" alt=\"\" class=\"wp-image-46232\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-26.png 687w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-26-300x82.png 300w\" sizes=\"auto, (max-width: 687px) 100vw, 687px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We stop the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl stop postgresql@18-main \nsudo umount \/pgdata<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We restore the snapshot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zfs rollback -r sqlpool\/pve\/vm-307-disk-0@pg_bench_20260803T224551 <\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"662\" height=\"35\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-27.png\" alt=\"\" class=\"wp-image-46233\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-27.png 662w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-27-300x16.png 300w\" sizes=\"auto, (max-width: 662px) 100vw, 662px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We mount the volume, start the service and check the logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mount \/pgdata \nsudo systemctl start postgresql@18-main<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This time the log shows a real recovery:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"141\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28-1024x141.png\" alt=\"\" class=\"wp-image-46234\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28-1024x141.png 1024w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28-300x41.png 300w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28-768x106.png 768w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28-1536x211.png 1536w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-28.png 1667w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Three differences compared to the first test:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The &#8220;last known up at&#8221; timestamp (20:44:36) does not match a checkpoint we ran manually. It matches the last automatic checkpoint triggered during the load.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The redo is not instantaneous anymore: 3.63 seconds, replaying about 280 MB of WAL (from LSN 20\/7A3618B0 to 20\/8BC0A4D0). All the write activity between the last checkpoint and the snapshot had to be replayed. The transactions committed before the snapshot are recovered, the ones that were in flight are rolled back.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The end-of-recovery checkpoint then writes everything the redo rebuilt in memory: 105355 buffers, 53.6% of the buffer pool. The database is ready to accept connections about 19 seconds after the service start.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The crash recovery completed correctly and the database has been restored. We verify the TPC-B invariant. Each pgbench transaction applies the same delta to the accounts, tellers and branches tables in a single transaction. On a consistent database, the three sums must be equal:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"539\" height=\"146\" src=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-29.png\" alt=\"\" class=\"wp-image-46237\" srcset=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-29.png 539w, https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-29-300x81.png 300w\" sizes=\"auto, (max-width: 539px) 100vw, 539px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 id=\"h-major-drawbacks\" class=\"wp-block-heading\">Major drawbacks<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The snapshot covers the whole zvol. All the databases of the cluster are captured and restored together. There is no per-database restore, unlike the METADATA_ONLY approach on SQL Server which targets a single database.<\/li>\n\n\n\n<li>There is no backup history. SQL Server records the metadata backup in msdb. Here, the only trace is the snapshot itself on the ZFS side.<\/li>\n\n\n\n<li>Point-in-time recovery is not covered. The snapshot alone brings the database back to the moment it was taken. For PITR, WAL archiving would still be required on top of it.<\/li>\n<\/ul>\n\n\n\n<h3 id=\"h-\" class=\"wp-block-heading\"><\/h3>\n\n\n\n<h2 id=\"h-conclusion\" class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The snapshot backup and restore model of the SQL Server series applies to PostgreSQL (no I\/O freeze, no metadata backup).<\/li>\n\n\n\n<li>One important rule: data files and WAL must reside on the same zvol so the snapshot is atomic.<\/li>\n\n\n\n<li>A 146 GB database was restored in a few seconds and in less than 20 seconds under active load, WAL replay included.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Thank you. <a href=\"https:\/\/www.linkedin.com\/in\/amine-haloui-76968056\/\">Amine Haloui<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the blog series I previously wrote, I did not answer all the customer&#8217;s questions. The last one was the following: Can this also be applied to PostgreSQL? In short, yes, it is possible. Let&#8217;s see how. Here is the list of the previous blog posts: Partitioning and filesystem We will reuse the sqlpool ZFS [&hellip;]<\/p>\n","protected":false},"author":147,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[229,198,83],"tags":[77,2974,935],"type_dbi":[2749],"class_list":["post-46203","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","category-database-management","category-postgresql","tag-postgresql","tag-proxmox","tag-zfs","type-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.1 (Yoast SEO v28.1) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4) - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4)\" \/>\n<meta property=\"og:description\" content=\"In the blog series I previously wrote, I did not answer all the customer&#8217;s questions. The last one was the following: Can this also be applied to PostgreSQL? In short, yes, it is possible. Let&#8217;s see how. Here is the list of the previous blog posts: Partitioning and filesystem We will reuse the sqlpool ZFS [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-03T22:13:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-03T22:33:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1187\" \/>\n\t<meta property=\"og:image:height\" content=\"155\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Amine Haloui\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Amine Haloui\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/\"},\"author\":{\"name\":\"Amine Haloui\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/221331d69d49c63fca67069b49b813fe\"},\"headline\":\"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\\\/4)\",\"datePublished\":\"2026-08-03T22:13:44+00:00\",\"dateModified\":\"2026-08-03T22:33:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/\"},\"wordCount\":1273,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/08\\\/image-1-1024x134.png\",\"keywords\":[\"PostgreSQL\",\"proxmox\",\"ZFS\"],\"articleSection\":[\"Database Administration &amp; Monitoring\",\"Database management\",\"PostgreSQL\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/\",\"name\":\"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\\\/4) - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/08\\\/image-1-1024x134.png\",\"datePublished\":\"2026-08-03T22:13:44+00:00\",\"dateModified\":\"2026-08-03T22:33:44+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/221331d69d49c63fca67069b49b813fe\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/08\\\/image-1.png\",\"contentUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/08\\\/image-1.png\",\"width\":1187,\"height\":155},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\\\/4)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/221331d69d49c63fca67069b49b813fe\",\"name\":\"Amine Haloui\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g\",\"caption\":\"Amine Haloui\"},\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/aminehaloui\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4) - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/","og_locale":"en_US","og_type":"article","og_title":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4)","og_description":"In the blog series I previously wrote, I did not answer all the customer&#8217;s questions. The last one was the following: Can this also be applied to PostgreSQL? In short, yes, it is possible. Let&#8217;s see how. Here is the list of the previous blog posts: Partitioning and filesystem We will reuse the sqlpool ZFS [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/","og_site_name":"dbi Blog","article_published_time":"2026-08-03T22:13:44+00:00","article_modified_time":"2026-08-03T22:33:44+00:00","og_image":[{"width":1187,"height":155,"url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1.png","type":"image\/png"}],"author":"Amine Haloui","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Amine Haloui","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/"},"author":{"name":"Amine Haloui","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/221331d69d49c63fca67069b49b813fe"},"headline":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4)","datePublished":"2026-08-03T22:13:44+00:00","dateModified":"2026-08-03T22:33:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/"},"wordCount":1273,"commentCount":0,"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-1024x134.png","keywords":["PostgreSQL","proxmox","ZFS"],"articleSection":["Database Administration &amp; Monitoring","Database management","PostgreSQL"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/","url":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/","name":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4) - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#primaryimage"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1-1024x134.png","datePublished":"2026-08-03T22:13:44+00:00","dateModified":"2026-08-03T22:33:44+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/221331d69d49c63fca67069b49b813fe"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#primaryimage","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1.png","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/08\/image-1.png","width":1187,"height":155},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-snapshot-backup-and-restore-with-proxmox-zfs-4-4\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"PostgreSQL Snapshot Backup and Restore with Proxmox ZFS (4\/4)"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/221331d69d49c63fca67069b49b813fe","name":"Amine Haloui","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/64707272207cd8d2667aefcb212f3ff5d19a15813da5aad6553f109d1f1afec1?s=96&d=mm&r=g","caption":"Amine Haloui"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/aminehaloui\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/46203","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/147"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=46203"}],"version-history":[{"count":18,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/46203\/revisions"}],"predecessor-version":[{"id":46253,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/46203\/revisions\/46253"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=46203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=46203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=46203"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=46203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}