Summary
supabase gen types typescript can produce a different committed file even when the Postgres schema is unchanged. The only diff is often __InternalSupabase.PostgrestVersion.
This makes schema drift checks (CI comparing regenerated types vs committed database.ts) noisy and forces consumers to strip metadata manually.
Motivation / workflow
A common setup:
- Local dev:
supabase gen types typescript --linked --schema public → commit database.ts
- CI (no remote token):
supabase start + supabase gen types typescript --local --schema public → compare to committed file
We expect the comparison to answer: “Did migrations / schema change?”
Instead, raw output can differ because of PostgREST version metadata, not because tables/columns changed.
Reproduction
CLI version: 2.116.0 (via npx supabase)
-
Generate types from a linked project and commit the file:
npx supabase gen types typescript --linked --schema public > database.ts
Note __InternalSupabase.PostgrestVersion (e.g. "14.15").
-
Without changing any migration or remote schema, run the same command again days later:
npx supabase gen types typescript --linked --schema public > database-fresh.ts
diff -u database.ts database-fresh.ts
-
Observed: diff is only:
- PostgrestVersion: "14.15"
+ PostgrestVersion: "14.5"
Table/column types (public.Tables.*) are identical.
-
Stripping __InternalSupabase / normalizing PostgrestVersion yields byte-identical schema output.
Why this hurts
git diff after gen types suggests a schema update when there was none
- CI drift checks on raw files false-fail unless consumers add custom normalization
- Cross-mode checks (
--linked vs --local) can differ in metadata even when migrations match
Current workaround
We normalize before compare (strip __InternalSupabase, normalize PostgrestVersion):
const normalize = (src) =>
src
.replace(/\r\n/g, '\n')
.replace(
/\n\s*\/\/ Allows to automatically instantiate createClient with right options\n\s*\/\/ instead of createClient<Database, \{ PostgrestVersion: 'XX' \}>\(URL, KEY\)\n\s*__InternalSupabase: \{\n\s*PostgrestVersion: "[^"]+"\n\s*\}\n/,
'\n',
)
.replace(/PostgrestVersion:\s*"[^"]+"/g, 'PostgrestVersion: "NORMALIZED"')
.trimEnd() + '\n';
This works but shouldn’t be required for “schema unchanged” to mean “types output unchanged (modulo metadata)”.
Related
- postgres-meta #959 (reproducibility)
- postgres-meta PR #948 (
postgrest_version in typegen)
Proposed directions (any one would help)
--schema-only (or similar) for drift checks: emit/compare only public tables/enums, omit __InternalSupabase
- Stable cross-mode output:
--linked and --local produce comparable files when schema matches
- Stable
PostgrestVersion in committed output: e.g. omit from default file, or write metadata to a separate generated file
- Document official CI drift-check pattern so teams don’t rely on ad-hoc regex normalization
Happy to provide a minimal repro repo or PR to docs if useful.
Environment
- Supabase CLI: 2.116.0
- Command:
gen types typescript --linked --schema public
- Schema: unchanged between runs; only
PostgrestVersion string changed
Summary
supabase gen types typescriptcan produce a different committed file even when the Postgres schema is unchanged. The only diff is often__InternalSupabase.PostgrestVersion.This makes schema drift checks (CI comparing regenerated types vs committed
database.ts) noisy and forces consumers to strip metadata manually.Motivation / workflow
A common setup:
supabase gen types typescript --linked --schema public→ commitdatabase.tssupabase start+supabase gen types typescript --local --schema public→ compare to committed fileWe expect the comparison to answer: “Did migrations / schema change?”
Instead, raw output can differ because of PostgREST version metadata, not because tables/columns changed.
Reproduction
CLI version:
2.116.0(vianpx supabase)Generate types from a linked project and commit the file:
npx supabase gen types typescript --linked --schema public > database.tsNote
__InternalSupabase.PostgrestVersion(e.g."14.15").Without changing any migration or remote schema, run the same command again days later:
npx supabase gen types typescript --linked --schema public > database-fresh.ts diff -u database.ts database-fresh.tsObserved: diff is only:
Table/column types (
public.Tables.*) are identical.Stripping
__InternalSupabase/ normalizingPostgrestVersionyields byte-identical schema output.Why this hurts
git diffaftergen typessuggests a schema update when there was none--linkedvs--local) can differ in metadata even when migrations matchCurrent workaround
We normalize before compare (strip
__InternalSupabase, normalizePostgrestVersion):This works but shouldn’t be required for “schema unchanged” to mean “types output unchanged (modulo metadata)”.
Related
postgrest_versionin typegen)Proposed directions (any one would help)
--schema-only(or similar) for drift checks: emit/compare onlypublictables/enums, omit__InternalSupabase--linkedand--localproduce comparable files when schema matchesPostgrestVersionin committed output: e.g. omit from default file, or write metadata to a separate generated fileHappy to provide a minimal repro repo or PR to docs if useful.
Environment
gen types typescript --linked --schema publicPostgrestVersionstring changed