allow_in_place_tablespaces

allow_in_place_tablespaces exists so the PostgreSQL test suite can test replication. That’s it. If you’re reading this as an operator, you will never touch it. But it’s in the alphabet, so here we are.

When off (the default), CREATE TABLESPACE requires a LOCATION that points to an existing, empty, absolute directory path. The server creates a symbolic link in $PGDATA/pg_tblspc/ pointing at that directory, and the relation files for that tablespace live out there. When on, you can pass an empty string — CREATE TABLESPACE ts_test LOCATION '' — and the server creates a real directory inside pg_tblspc/ instead of a symlink. Data lives directly in the data directory tree.

Why does this exist? Primary and standby servers running on the same machine, sharing the same host filesystem, cannot both have a tablespace at /mnt/fast_disk/ts_test — they’d collide. Without in-place tablespaces, testing physical replication of tablespace-containing databases requires either two separate disks or some kind of path-remapping dance. Added in PostgreSQL 15, the feature lets each cluster keep its tablespaces inside its own $PGDATA and stay out of each other’s way. The regression tests use it. You will not.

And here is why you will not. Backup and replication tools read pg_tblspc/ and expect to find symbolic links. That’s been the contract since tablespaces shipped in 8.0. An in-place directory sitting there instead is, per the docs, “likely to confuse” them — which in practice means your backup silently does the wrong thing, or your base backup fails in an interesting way. The parameter is listed under Developer Options for a reason. The docs are explicit that parameters in that section have no business on a production database.

Context is superuser, default off, changeable at the session level — so a superuser can flip it on long enough to create a tablespace, run a test, and drop it, which is how the test suite uses it.

Recommendation: Leave it off. If you think you need it, you probably want a second machine, not this.

(This is #2 in a series on every PostgreSQL GUC as of version 18, in alphabetical order.)