Run this checklist every time you write a new Postgres/RPC function exposed via supabase.rpc().

Standard: RPC & Postgres Function Standards


1. Decision





2. SECURITY INVOKER vs SECURITY DEFINER




[ ] auth.uid() captured as the FIRST line of the DECLARE block

[ ] auth.uid() validated: IF v_user_id IS NULL THEN RAISE EXCEPTION 'AUTH_REQUIRED...'

[ ] Manual permission checks replace RLS checks

[ ] Reviewed by a second developer before merging


3. Function Signature





[ ] UUIDs typed as uuid (not text)

[ ] Timestamps typed as timestamptz (not timestamp)

[ ] Dates typed as date (not text)

[ ] Booleans typed as boolean (not text or integer)

[ ] Arrays typed correctly: uuid[], text[]




4. Return Type


[ ] RETURNS json — single record or mixed data

[ ] RETURNS TABLE — multiple rows with known columns

[ ] RETURNS void — side effects only


json_build_object('data', row_to_json(v_record), 'message', '...')



5. Validation Order

All validation done in this order — stop at first failure:










6. Error Raising



[ ] AUTH_REQUIRED — user not authenticated

[ ] VALIDATION_ERROR — field-level validation failure

[ ] NOT_FOUND — FK target or entity does not exist

[ ] FORBIDDEN — not a member or wrong role

[ ] DUPLICATE — uniqueness violation

[ ] BUSINESS_RULE_VIOLATION — business constraint violated

[ ] SERVER_ERROR — unexpected/catch-all error



7. Transaction Safety






8. Performance








9. Documentation







10. Testing












Done When










Practice Task

Archive Project RPC Function Build an atomic RPC that archives a project, sets all open tasks to on-hold, and writes an audit log — in one transaction, with full validation.