Skip to content
Sarj Code Standards

no-database-functions

Ban stored SQL functions and procedures in migrations.

Why

Under a single-writer application architecture, stored functions can obscure application behavior. Migration behavior must remain explicit in application transactions or declarative constraints.

Fix

Prefer declarative constraints or explicit transactional application behavior where equivalent. Preserve transaction atomicity and database-enforced integrity; migrations cannot waive this rule with an inline suppression.

Examples

Before — flagged An executable anonymous block still creates a stored function
migrations/001_function.sql
DO $outer$ BEGIN CREATE FUNCTION app.f() RETURNS integer LANGUAGE sql AS $inner$SELECT 1$inner$; END $outer$;
After — preferred Function DDL stored as scalar data does not execute
migrations/001_function.sql
SELECT
$outer$CREATE FUNCTION app.f() RETURNS integer LANGUAGE sql AS $inner$SELECT 1$inner$;$outer$;
Before — flagged Procedural database fault fixture
supabase/migrations/001.sql
CREATE FUNCTION fail_counter () RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'failure'; END $$;
After — preferred Declarative constraint in a disposable test database
supabase/migrations/001.sql
ALTER TABLE batch
ADD CONSTRAINT fail_counter CHECK (FALSE) NOT VALID;