Skip to content

gen types: PostgrestVersion / __InternalSupabase causes false diffs without schema changes #6390

Description

@scs0209

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:

  1. Local dev: supabase gen types typescript --linked --schema public → commit database.ts
  2. 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)

  1. 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").

  2. 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
  3. Observed: diff is only:

    -    PostgrestVersion: "14.15"
    +    PostgrestVersion: "14.5"

    Table/column types (public.Tables.*) are identical.

  4. 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)

  1. --schema-only (or similar) for drift checks: emit/compare only public tables/enums, omit __InternalSupabase
  2. Stable cross-mode output: --linked and --local produce comparable files when schema matches
  3. Stable PostgrestVersion in committed output: e.g. omit from default file, or write metadata to a separate generated file
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions