ignore_system_indexes completes a run of three consecutive parameters named ignore_-something, and it is by a comfortable margin the most polite of the family. ignore_checksum_failure and ignore_invalid_pages tell PostgreSQL to proceed past evidence of corruption; this one just tells it to stop trusting a set of access paths. It is a boolean, default off, and it lives in the rare backend context: it can only be set before a session exists, either in postgresql.conf (affecting new sessions only) or at connection time, most conveniently as PGOPTIONS="-P", the equivalent server switch. SET it after connecting and you get an error. In every supported version it is one of exactly two parameters with this context (the other is post_auth_delay), it is classified as a Developer Option, and it does not appear in the sample configuration file. All of which is the server’s way of saying: you were not supposed to find this.

What it does is simple and nearly complete. With it on, every internal catalog lookup that would normally probe an index (a syscache miss, a relcache build, a dependency walk) opens no index at all and sequentially scans the catalog heap instead. The planner cooperates: indexes on system relations are dropped from consideration, so even your own SELECT relname FROM pg_class WHERE oid = ... plans as a Seq Scan on pg_class. Catalog writes still maintain every index, so the indexes do not drift while being ignored. (initdb runs its bootstrap phase in this mode, for the excellent reason that the indexes do not exist yet.)

The point of all this is index corruption in the system catalogs, which is the one flavor of index corruption you cannot repair the normal way. REINDEX of a catalog index needs catalog lookups to get started, and those lookups want catalog indexes; worse, if pg_class_oid_index is sufficiently scrambled, backends crash during startup and you never get to type anything. The canonical recovery is: stop the server, start a single-user backend with postgres --single -P -D $PGDATA yourdb, run REINDEX SYSTEM; (PostgreSQL 14 still insists you append the database name), quit, start the server normally. If sessions can still start, PGOPTIONS="-P" psql against the running server does the same job; lock everyone else out while you operate. Managed services have no single-user mode, so if catalog indexes there are damaged badly enough to kill connections, the tool is a restore and a support ticket, not this parameter.

The parameter protects reads only. Catalog writes still insert into every index, uniqueness checks included, and inserting into a corrupt B-tree is its own adventure; once you are in that -P session, go directly to REINDEX SYSTEM and do not run DDL first.

It also leaks. A few internal scans need index order to be correct rather than merely fast (TOAST fetches, large objects, some enum comparisons, the event trigger cache), and those use the index anyway while emitting WARNING: using index ... despite IgnoreSystemIndexes. In practice a -P session is noisy: reading any TOASTed value warns, and even querying a view warns, because view definitions live TOASTed in pg_rewrite. If the corrupt index is a TOAST index, this parameter does not route around it.

The parameter’s built-in description promises that “The worst consequence is slowness.” Almost. Slowness, certainly; a catalog cache miss that seqscans a multi-hundred-megabyte pg_attribute is a memorable experience. But there is one behavioral change: triggers and rules fire in name order only because PostgreSQL reads them through a name-ordered index, and with that scan degraded to a heap scan, they fire in physical row order instead. I confirmed this on a scratch cluster: create zz_first, then aa_second, and under -P they fire in creation order. Nobody should care, because nobody should run a working system this way; if you have ignore_system_indexes on and order-sensitive trigger chains, your day was already going badly.

The -P switch itself is old. The PostgreSQL 7.0 source allowed it only from the server command line, next to a comment wondering whether it would be safe to let clients set it; 8.2 answered yes, made it a GUC, and today any user, superuser or not, can start a session with it. Harmless, apart from the self-inflicted slowness.

Leave it off, everywhere, always; it is a crash cart, not a configuration. On the day you need it: single-user, -P, REINDEX SYSTEM;, then bt_index_check from amcheck over the catalog indexes to confirm the rebuild. Then go find out what corrupted an index on your system tables, because indexes do not corrupt themselves.