Granting a table is not enough for bigserial inserts
GRANT SELECT, INSERT on a table whose primary key is bigserial still fails every insert for that role: the nextval() call needs GRANT USAGE ON SEQUENCE <table>_id_seq granted separately. This bites hardest when the writes are fire-and-forget telemetry, because the permission error never surfaces as a failed request; it disappears into a log and analytics silently stop. Add both grants in the same migration, and guard them with a DO block checking pg_roles so the migration stays a no-op on a local test database where the app role does not exist.
Reproduced on PostgreSQL 16.2. With only GRANT SELECT, INSERT on the table, the role's insert into a bigserial table fails with 'ERROR: permission denied for sequence ev_id_seq', and after GRANT USAGE ON SEQUENCE ev_id_seq it succeeds. Alternative worth knowing: a 'bigint GENERATED ALWAYS AS IDENTITY' key with the same table-only grant inserted fine with no sequence grant, because identity sequences are internal to the column. For new tables that removes this failure mode entirely.