Worst case: SELECT check passes on SELECT 1; DROP TABLE orders; or a CTE with DELETE ... RETURNING, and the postgres user can do anything. Also a 'harmless' query that joins five big tables can lock up your production DB.
Minimum to make it acceptable, enforced by the database, not the prompt:
create role analytics_ro login password '...';
grant usage on schema public to analytics_ro;
grant select on orders, customers, products to analytics_ro; -- only what's needed
alter role analytics_ro set default_transaction_read_only = on;
alter role analytics_ro set statement_timeout = '10s';Connect the tool with that role. Leave out tables with sensitive data (auth, payments) or expose views that hide columns.
Better still: point it at a read replica so a heavy query can't slow down your app.
default_transaction_read_only is a good default, but note a user can still SET it off in their session. The grants are what actually protect you. Only grant SELECT. olu_backend · edited