It would be incredibly helpful if the Supabase Dashboard tracked the history of database functions. Specifically, when looking at a function in the UI, I would love to see:
I am using AI-assisted development, leveraging AI agents via MCP to write and execute multiple RPC functions directly in the database.
The issue I frequently encounter is that my AI agent sometimes calls a raw execute_sql tool to push updates rather than using an apply_migration tool. Because it sometimes bypasses the proper tool, there is no consistent migration tracking for these changes.
On top of that, the agent often hits intermittent errors—like framework timeouts, network drops, or internal agent crashes—right as it executes the SQL. When the agent crashes mid-task, it leaves me completely in the dark. Because the raw tool leaves no migration history trailing behind it, I have no idea if the CREATE OR REPLACE FUNCTION command actually went through successfully, or if it failed right before committing.
Right now, the only way to find out is to manually copy code out of the dashboard and diff it against my local files, which significantly slows down my workflow. Having a quick visual timeline in the Supabase Dashboard would save a ton of time, allowing me to instantly verify exactly what my AI successfully updated before it crashed.
The user requests a feature in the Supabase Dashboard to track the history of database functions, including timestamps and code diffs. This would aid in AI-assisted development workflows, where AI agents execute SQL updates. Current issues include lack of migration tracking and uncertainty after agent crashes. Suggestions include using PostgreSQL features for current function definitions and implementing a logging mechanism for changes.
For the “did the RPC update actually commit before the agent disconnected?” problem, a read-only check from a new connection can remove the uncertainty about the current definition:
-- Replace this with the function's schema, name, and exact input types.
select pg_get_functiondef(
to_regprocedure('public.my_rpc(uuid)')
) as current_definition;
This handles overloaded functions by specifying the input types. If that exact function does not exist, the result is NULL. Compare the returned definition with the intended migration, and test the RPC's behavior separately. This shows the currently committed definition visible to that connection; it does not reconstruct previous versions or prove which particular request committed.
PostgreSQL's pg_proc catalogue does not store ordinary per-function created_at / updated_at timestamps. pg_get_functiondef reconstructs the current definition. A timeline of earlier definitions needs to be recorded before changes occur; it cannot be recovered from the current function definition alone.
For future agent changes, a practical workaround is to save each CREATE OR REPLACE FUNCTION in a versioned migration and commit that file to Git. That gives you a reviewable diff and a link between the proposed SQL and the recorded deployment. Keep raw SQL execution for inspection, and route schema changes through the migration workflow. Instructions help, but if an agent can still write arbitrary SQL, they are not an enforced access boundary.
Supabase's migration guide explains the distinction: Git tracks the SQL files; supabase_migrations.schema_migrations tracks applied migrations. supabase migration list can compare local and remote records. A raw execute_sql change will not gain migration history retroactively merely by checking that table.
This is a workaround for verification and future history, rather than an implementation of the proposed Dashboard timeline.
Prepared with AI assistance. The definition query was checked against created, replaced, and missing functions in an isolated PostgreSQL 17 instance; no access to your project was used.
the pg_get_functiondef check tells you what's live right now. if you want to stop guessing after a crash next time, make the agent's change leave a receipt that commits together with it. ddl is transactional in postgres, so:
begin;
create or replace function public.my_rpc(p uuid) ...;
insert into agent_changes (op_key, object_name, applied_at)
values ('my_rpc-v7', 'public.my_rpc', now());
commit;
with op_key unique. after a crash you look up the op_key: row there means the function change landed, no row means nothing did. no half state and no diffing against local files. it also gives you a rough timeline of what the agent changed, as long as it goes through that path.
if your project lets you create event triggers, one on ddl_command_end that logs pg_get_functiondef into a table would catch the execute_sql bypasses too, since it fires no matter which tool sent the sql.
(the receipt in the same transaction is the same trick we use in ledgerguard for agent data writes, not ddl: https://github.com/Val1-IT/Arvanta-Ledgerguard)