"Who deleted this row?"
If you run a Supabase app, you will hear this question. A customer says their order vanished. A teammate swears they didn't touch the pricing table. You open the Dashboard and find… nothing. There is no record of who changed what.
Supabase has three kinds of "audit" built in, and none of them answers the question:
- pgAudit logs which SQL ran. It does not store the old and new values of the row.
- Auth Audit Logs record logins and sign-ups. Not data changes.
- Platform Audit Logs record Dashboard actions. Not app data changes.
The tool that used to fill this gap was supa_audit, Supabase's own trigger-based audit extension. As of November 2026, its GitHub page says Public archive — 670 stars, 45 forks, no maintenance. The README also warns against enabling it on tables above ~3k ops/sec, and it never had an actor field, restore, retention, or a UI.
So I built the smallest correct replacement, and put it on GitHub for free.
The Lite version (free, MIT)
Repo: https://github.com/liulewis/supabase-audit-log-lite
It is a trigger-based audit log, about 150 lines of SQL:
-
audit.audit_log— one row per INSERT / UPDATE / DELETE, with old/new values as JSONB, the acting user'sauth.uid(), and a timestamp. - It lives in its own
auditschema, so the Data API never exposes it. - RLS is on, authenticated users get
SELECTonly. There is deliberately no write policy, so the log is append-only through the API. - Two query views: history of one row, and activity of one person.
Setup is three steps in the SQL Editor:
-- 1. run sql/01_audit_schema.sql, then sql/02_views.sql -- 2. turn auditing on for the tables you care about select audit.enable_tracking('public.customers'); select audit.enable_tracking('public.orders'); -- 3. "who deleted this row?" select changed_at, operation, actor_id, old_data, new_data from audit.v_row_history where table_name = 'customers' and record_id = '42' order by changed_at desc; There is a demo script (sql/03_demo.sql) that inserts, updates and deletes a throwaway row so you can see the three audit entries appear.
What Lite honestly does NOT do
I would rather list the gaps than have you discover them:
- No field-level diff. Lite stores the full old/new row.
- No single-row restore. Restoring a deleted row correctly — foreign keys, unique keys, concurrency — is the hardest part and is not in Lite.
- No retention management. The log only grows. Watch your 500 MB free-tier database.
- No tamper-resistance depth. Lite relies on RLS + no write policy. No
BEFORE UPDATE/DELETEguards, noTRUNCATEprotection. - No admin UI. You query with SQL.
- No actor for background writes.
actor_idisauth.uid()for changes through PostgREST. Writes fromservice_role, Edge Functions, cron or direct SQL recordNULL. - TRUNCATE is not captured. Row-level triggers don't fire on it.
The full kit (presale)
I am building the full version as a one-time template — diff views, single-row restore, retention governance, tamper-resistance depth, the admin UI, and actor context for background jobs. Presale is $29 (launch price, then $39):
Presale: https://franklinlewis7.gumroad.com/l/audit-log-kit
What I need from you
This is a validation post as much as a launch post. If you have ever needed an audit trail on Supabase, tell me:
- What was the scenario — compliance, customer support, debugging, or showing history to your own users?
- How many writes per second do your audited tables see?
- Would you pay $29 once for diff + restore + retention + UI, or is the free Lite enough?
Try the Lite, star the repo if it helps, and leave a comment. If enough people need the full version, I will build it. If not, the Lite stays free and I will say so.
