ident_file tells the server where pg_ident.conf lives. That is the whole feature. The interesting part is what happens when it’s wrong, which is: nothing, loudly, in a log nobody is reading.
The default is pg_ident.conf in the configuration directory, which is the directory holding postgresql.conf and not necessarily the data directory. The context is postmaster, so changing it requires a restart, and it carries the superuser-only flag, so a non-privileged role asking SHOW ident_file gets a permission error rather than an answer. A relative path is resolved against the working directory of whoever started postgres, not against PGDATA.
That last one is worth a moment. Start the same cluster from two different directories with ident_file = 'pg_ident.conf' and you get two different files:
1 cwd=/tmp/cwdtest -> ident_file = /tmp/cwdtest/pg_ident.conf
2 cwd=/ -> ident_file = /pg_ident.conf
Use an absolute path. Always.
The part that actually matters
pg_hba.conf and pg_ident.conf are not treated alike. If hba_file points at a file that isn’t there, the postmaster refuses to start:
1 LOG: could not open file "/tmp/nope.conf": No such file or directory
2 FATAL: could not load /tmp/nope.conf
If ident_file points at a file that isn’t there, the server starts. It logs a single LOG line, sandwiched between the “listening on” messages and “database system is ready to accept connections,” and then runs with no user maps at all. The comment in postmaster.c is explicit that this is deliberate: you can come up without the ident file, you just can’t use any authentication method that needs a mapping. Which is ident, peer, gssapi, sspi, cert, and, as of PostgreSQL 18, oauth.
So the failure looks like this. Deployment goes out, the server comes up green, health checks pass, and then every application connection that relies on map= fails with no match in usermap. Nothing is down. Authentication is just gone.
A broken reload is worse, because the server keeps working. pg_reload_conf() on a malformed pg_ident.conf logs a parse error and pg_ident.conf was not reloaded, and the previously-loaded maps stay resident. I removed a mapping from the file, broke the syntax, reloaded, and the deleted mapping still authenticated. The map you think you revoked is still live until something restarts the postmaster or you fix the syntax error, and the thing that eventually restarts the postmaster is usually not you at a keyboard on a Tuesday afternoon.
Reading it back
pg_ident_file_mappings (PostgreSQL 15 and up, superuser or pg_read_all_settings) is where you check the work. It gives you file_name, line_number, map_name, sys_name, pg_username, and error per line, and it resolves include directives, so a map pulled in from an included file shows its own filename:
1 map_number | file_name | line_number | map_name
2 ------------+------------------------------+-------------+----------
3 1 | /tmp/altident/pg_ident.conf | 1 | appmap
4 2 | /tmp/altident/inc/extra.conf | 1 | othermap
The catch: it opens IdentFileName and parses it fresh every time you query it. It reports what is on disk, not what the postmaster has in memory. During the failed-reload window above, the view showed the broken file while the server was happily authenticating against maps that no longer existed anywhere. The view is your check on the file; it is not your check on the server. For the server, the log line is all you get, so alert on was not reloaded.
Setting it
Mostly, don’t. If you’re on Debian or Ubuntu it’s already set for you, to /etc/postgresql/NN/main/pg_ident.conf, alongside hba_file and data_directory, and that’s a perfectly good arrangement. If you’re on stock packaging and your configuration lives in the data directory, leave it alone. The case for setting it is the same as for hba_file: you keep configuration outside PGDATA so it can be version-controlled and backed up separately, in which case set both, absolutely, in postgresql.conf.
ALTER SYSTEM SET ident_file is permitted, which surprised me; data_directory and config_file are flagged against it and these two are not. Don’t. postgresql.auto.conf is read from the data directory, so you’d be storing the pointer to your externalized authentication configuration inside the thing you externalized it from, and it still needs a restart.
When authentication is broken and you’re trying to work out why, the first query is SHOW ident_file and the second is SELECT * FROM pg_ident_file_mappings. More than once the answer has been that the file being carefully edited was not the file the server had ever read.