API Design's own domain taught REST conventions as something a team designs and implements deliberately, endpoint by endpoint. Supabase skips that implementation step almost entirely for the common case — every table in your database already has a working REST API the instant you create it.
2 min read
Table "documents" with columns (id, title, owner_id, created_at)
→ automatically available at:
GET /rest/v1/documents
POST /rest/v1/documents
PATCH /rest/v1/documents?id=eq.5
DELETE /rest/v1/documents?id=eq.5
PostgREST, the open-source engine Supabase's auto-generated API is built on, introspects your database's actual schema and generates a full REST API from it directly — no endpoint code to write, no serializer to define, no router to configure. Creating a new table via a migration (lesson 9) makes that table's API available immediately, with the same CRUD operations available for every table, generated from the schema alone.
GET /rest/v1/documents?status=eq.published&order=created_at.desc&limit=10
Filtering, sorting, and pagination are all expressed as query-string parameters following PostgREST's own specific syntax (eq., gt., order=column.desc) — genuinely powerful for straightforward cases, and a real, different paradigm from API Design's own domain, which covers hand-designing a query/filtering convention deliberately; here, the convention is fixed by PostgREST itself, and the actual design work shifts to designing the database schema correctly, since the API's shape is a direct, automatic consequence of it.
Because the generated API is just a thin HTTP layer over direct Postgres queries, RLS policies (lesson 2) apply to every request through this API exactly as they would to a raw SQL query — the API itself has no separate authorization logic layered on top; Postgres's own row-level policies are the actual enforcement, for every endpoint, automatically. This is a genuinely different security model than a hand-built REST API, where each endpoint's handler code is individually responsible for checking authorization — here, the enforcement is structurally impossible to forget per-endpoint, because there's no per-endpoint authorization code to forget it in.
A genuinely complex business operation — charging a customer, running a multi-step calculation, enforcing a rule that spans several tables atomically — doesn't have a natural, single-table CRUD shape the auto-generated API can express directly. This is exactly the gap Postgres functions (lesson 8) and Edge Functions (lesson 7) exist to fill: the auto-generated API handles the common "read/write a row" case extremely well, and genuinely custom logic still needs a genuinely custom implementation somewhere, whether inside the database itself or in a function layered on top.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. How does PostgREST generate a REST API for a Supabase project?
2. Why does RLS apply automatically to every request through the auto-generated API, with no separate authorization code per endpoint?
3. What kind of operation does the auto-generated API NOT handle cleanly?
Supabase