Security and Access Control
Roles
PostgreSQL has one concept: the role. CREATE ROLE ... LOGIN is a user; without LOGIN it is a group. Attributes include SUPERUSER, CREATEDB, CREATEROLE, REPLICATION and BYPASSRLS. Membership (GRANT group TO user) is inherit-by-default, unlike OS groups. PUBLIC is a pseudo-role meaning every role.
Privileges
Privileges are per object class: database (CONNECT, CREATE, TEMP), schema (USAGE, CREATE), table (SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER), column, sequence (USAGE, SELECT, UPDATE) and function (EXECUTE). Reading a table requires both USAGE on its schema and SELECT on the table. Owners hold all privileges implicitly and may grant them onward. ALTER DEFAULT PRIVILEGES is needed because a GRANT applies only to objects that exist at that moment.
Authentication
pg_hba.conf is read top-down and the first matching line wins; entries key on connection type (local/host/hostssl), database, user, address and method. Methods: trust (no password), peer (OS user, local sockets only), ident, md5, scram-sha-256 (default since v14, governed by password_encryption), and cert. Apply changes with SELECT pg_reload_conf().
Row-level security
ALTER TABLE t ENABLE ROW LEVEL SECURITY followed by CREATE POLICY. With RLS enabled and no policy, non-owners see no rows. Owners and BYPASSRLS roles bypass policies unless FORCE ROW LEVEL SECURITY is set.
Traps
SECURITY DEFINER functions execute with the owner's rights - always pin search_path inside them. Leaving the public schema writable by PUBLIC is a common audit finding (fixed by default in v15).
Rule of thumb
Least privilege: per-application login roles, permissions granted through group roles, and applications never connecting as superuser.