Alphabetical order delivers our first casualty. archive_cleanup_command is a standby-server knob that exists entirely to tidy up after archive_command, which the alphabet insists on deferring until the next post. So we will describe how to sweep up a party we have not yet thrown.

The briefest-possible backfill: a PostgreSQL primary can archive its WAL segments to some location — a directory, an S3 bucket, an NFS share — by running a shell command on each segment as it fills. Standbys read from that location to catch up, and backup tools read from it to enable point-in-time recovery. Files pile up. Something has to delete them.

archive_cleanup_command is one option for that something. It runs on a standby server at every restartpoint (roughly the standby’s equivalent of a primary checkpoint) and deletes WAL segments the standby no longer needs to recover forward. The GUC takes a shell command, typically invoking pg_archivecleanup:

1archive_cleanup_command = 'pg_archivecleanup /mnt/archive %r'

The %r placeholder expands to the oldest WAL file the standby still needs; pg_archivecleanup deletes everything strictly older. Context is sighup; default is empty.

Two things worth knowing.

It is dangerous in exactly the setup people most often have. The tool is safe only if the archive is, per the docs, “a transient staging area for this particular standby server.” If your archive doubles as the source for backup-tool PITR, or if multiple standbys read from it, running archive_cleanup_command on one standby will happily delete files the others still need. You will learn this during a restore, which is the worst possible time.

If you are using a real backup tool, you do not want this at all. pgBackRest, Barman, and WAL-G all manage archive retention based on backup policies and replica state, and they handle it correctly across multiple consumers. Setting archive_cleanup_command on top of that is redundant at best and actively harmful at worst — a way to delete files your backup tool was planning to keep.

Historical note: this parameter lived in recovery.conf until PostgreSQL 12 folded that file into postgresql.conf. If you are reading ancient operations documentation, that is where it will be hiding.

Recommendation: Leave it empty. Use a backup tool that manages archive retention, and let it do its job. The only time to set archive_cleanup_command is in a toy HA setup with one standby and no backups worth keeping — which is to say, not production.