Supabase audit logs record the dashboard, not the database

Three different features get called logs in Supabase, and people looking for an audit trail usually find the wrong one first. Here is what each actually records, which question each can answer, and where the gap sits between them.

Short answer

Supabase organization audit logs record control-plane actions — what your team did in the dashboard and management API, such as inviting a member, changing a project setting, or pausing a project. They do not record what happened to your data.

Data-plane activity lives in the Logs Explorer instead: API requests, auth events, Postgres output, Edge Function invocations. Neither surface records who deleted a row, because Postgres does not log ordinary INSERT, UPDATE or DELETE statements unless pgAudit or audit triggers are configured first.

Three things called logs

The confusion is worth clearing up before anything else, because the three surfaces answer different questions and only one of them is on by default in a form you can investigate with.

SurfaceRecordsAnswers
Organization audit logsDashboard and management API actions by your team membersWho changed the project, and when
Logs ExplorerAPI, auth, Postgres, Edge Function and storage traffic — edge_logs, auth_logs, postgres_logs and the restWhat requests hit the project
Audit trail in the databaseNothing, until you set up pgAudit or triggersWhich rows changed, and how

The audit log watches your team, not your attacker

An organization audit log is a record of privileged human actions on the platform. Someone invited a collaborator; someone rotated a key; someone turned Row Level Security off on a table. That is genuinely useful, and it is the first place to look after a configuration change nobody admits to making.

But it is scoped to the control plane. Traffic that arrives with an API key never touches it. Your application does not appear in it. Neither does a leaked service_role key reading every row of every table, nor a coding agent connected to production, nor an anonymous request that Row Level Security should have filtered and did not. Those are all data-plane events, and the audit log is structurally blind to them.

This matters because the two surfaces tell one story between them. The audit log shows RLS being disabled on Tuesday. The Logs Explorer shows the volume of anonymous reads from that table on Wednesday. Neither entry is alarming alone, and nothing in Supabase joins them for you.

Postgres does not record who deleted the rows

This is the assumption that costs people the most time. postgres_logs exists, so it feels reasonable to expect that a destructive statement left a trace in it. By default it did not: Postgres logs errors, slow queries and connection events, not the text of every successful INSERT, UPDATE and DELETE. When the rows are gone and you go looking for the statement that removed them, there is nothing there.

Two ways to fix that, with different costs:

-- Row-level change history, kept in the database rather than the log stream
create extension if not exists supa_audit cascade;
select audit.enable_tracking('public.members'::regclass);

-- Every change to public.members from here on
select * from audit.record_version order by ts desc limit 20;

Note what neither approach gives you on its own: identity. A log line names the Postgres role that ran the statement, which for anything arriving through PostgREST is authenticated or anon, not a person. Tying a change back to an end user means capturing auth.uid() in the audit record yourself — and a statement run with the service_role key has no user to capture, which is the point at which an audit trail stops being able to answer the question at all.

Everything expires on a schedule you did not choose

Both the audit log and the Logs Explorer keep a window set by your plan, and at the low end that window is measured in days. Set that against how long breaches typically go undiscovered and the arithmetic is uncomfortable: by the time there is a reason to audit, the audit trail has rolled over.

Upgrading buys a longer window and a larger bill without changing the shape of the problem — the log retention guide works through why paying to keep routine traffic is the wrong lever, and what to keep instead.

What an audit trail is actually for

An audit log you read after an incident is forensics. It is worth having, and it is the wrong instrument for the job everyone actually wants done, which is finding out on Wednesday rather than in November.

Defencecore reads your Supabase logs continuously, normalizes them, and applies detection rules as events arrive — a spike in RLS denials after a migration, authentication patterns that look like credential stuffing, a read volume that does not match the number of users online. When a rule matches, it opens an incident and attaches the log lines that triggered it. Those stay readable after the originals age out of Supabase, so the evidence outlives the retention window that would otherwise have destroyed it. Access is read-only: it can explain what happened to your database, never cause it.

Frequently asked questions

Does Supabase have audit logs?
Supabase has an organization audit log that records what people did in the dashboard and management API — who invited a member, who changed a project setting, who paused a project. It is scoped to your team's actions on the platform. It does not record what your application, your service_role key, or a coding agent did to the data inside the database.
Do Supabase logs show who deleted a row?
Not by default. Postgres does not log the text of ordinary DML statements unless it is configured to, and even then a log line records the statement and the connecting role rather than the end user behind it. Answering 'who deleted this row' requires either pgAudit or an audit table populated by triggers, set up before the deletion happens.
What is the difference between Supabase audit logs and the Logs Explorer?
The audit log covers control-plane actions: changes to the project and the organization, made by your team. The Logs Explorer covers data-plane traffic: API requests, auth events, Postgres output, Edge Function invocations. A dashboard user disabling Row Level Security appears in the audit log. An attacker exploiting the fact that it is disabled appears only in the Logs Explorer.
How long are Supabase audit logs kept?
Retention is set by plan and is short at the low end — long enough to answer a question you already know to ask, not long enough for an investigation that starts weeks later. Since breaches are typically discovered long after they begin, the audit trail that would explain one has often expired before anybody opens it.