name: gotrue-postgrest-url-separation
description: Fix Supabase self-hosted GoTrue admin calls going through wrong Kong route (404 errors on user CRUD)
Supabase Self-Hosted: GoTrue vs PostgREST URL Separation
Context
On Supabase self-hosted (Docker on VPS), the API gateway (Kong) routes traffic to two different backend services:
- - PostgREST (port 3000): serves
/rest/v1/*— handles RLS, serves public tables, auth-aware - - GoTrue (port 9999): serves
/auth/v1/*— handles user management, admin ops - -
apikeyheader alone → PostgREST uses service role (bypasses RLS) - -
Authorization: Bearer {SERVICE_ROLE_KEY}→ GoTrue validates as service admin - - NEVER mix them: Do NOT send
Authorization: Bearerto PostgREST (it validates as user JWT with JWT_SECRET, not service role key → 401)
Both are behind Kong at http://kong:8000. Kong routes based on path prefix.
The Bug
When calling GoTrue admin endpoints (create/update/delete/list users), using the same helper that calls PostgREST will fail because:
`
SUPABASE_URL/rest/v1/auth/v1/admin/users → POSTGREST → 404
`
The /rest/v1 prefix routes to PostgREST, not GoTrue. GoTrue lives at /auth/v1/.
The Fix
Always separate the two:
`typescript
// PostgREST calls (tables, RLS) — uses apikey only, no Bearer
const dbFetch = async (endpoint: string, options: RequestInit) => {
const url = ${SUPABASE_URL}/rest/v1${endpoint};
const response = await fetch(url, {
...options,
headers: {
apikey: SERVICE_ROLE_KEY,
"Content-Type": "application/json",
...options.headers,
},
});
return response;
};
// GoTrue calls (user management) — uses apikey + Authorization Bearer
const authFetch = async (endpoint: string, options: RequestInit) => {
const url = ${SUPABASE_URL}/auth/v1${endpoint};
const response = await fetch(url, {
...options,
headers: {
apikey: SERVICE_ROLE_KEY,
Authorization: Bearer ${SERVICE_ROLE_KEY},
"Content-Type": "application/json",
...options.headers,
},
});
return response;
};
`
GoTrue admin endpoints: /admin/users, /admin/users/:id, /admin/users/:id/sessions
PostgREST endpoints: /rest/v1/{table} etc.