Le Duy Khuong

Chuỗi: supabase-series · Phần 8

Năng suất & công cụ dev

API: PostgREST, custom API và khi nào dùng gì

PostgREST auto API; khi nào dùng custom API (backend riêng). REST contract rõ ràng; tách biệt consumer và data.

2026-03-173 phút đọcVI

API: PostgREST vs custom API and when to use which

Introduction

Supabase provides PostgREST: a REST API generated from your Postgres schema (CRUD by table, filter, sort, pagination). Sometimes you need complex logic, multiple tables, webhooks or external integration → then you write a custom API (NestJS, Express, FastAPI) that calls Supabase (DB or PostgREST). This post compares PostgREST and custom API, when to use which, and how to keep a clear REST contract.

Goal: Choose the right channel (PostgREST vs your own backend) and design a consistent API (contract, versioning if needed).

Features

PostgREST

  • Automatic: Each table (e.g. conversations) → resource GET/POST/PATCH/DELETE /rest/v1/conversations. Filter via query (?id=eq.xxx), select columns, order, limit/offset. Header Authorization: Bearer <jwt>; RLS applies.
  • Pros: No need to write endpoints; schema change (new column) → API gets it. Good for simple CRUD and frontend calling directly.
  • Limits: Complex logic (multi-step, transaction, external services) does not live in PostgREST; you need a separate backend or Edge Function.

Custom API

  • Your backend: NestJS, Express, FastAPI, etc. on server/Vercel/Lambda. Can use Supabase client (service role) to read/write DB or call PostgREST; or Prisma/raw SQL.
  • Use when: Multi-step workflows, transactions, webhooks, sending email, calling third-party APIs; or when you want to hide schema (API contract different from table structure).

Workflow / Process

  1. Định hình use case: Chỉ CRUD đơn giản, frontend có JWT → dùng PostgREST. Có logic phức tạp hoặc cần ẩn DB → thiết kế endpoint custom.
  2. Contract rõ ràng: Dù PostgREST hay custom, định nghĩa “client gọi gì, nhận gì” (method, path, body, response). Custom API nên có OpenAPI/Swagger hoặc doc tĩnh.
  3. Phân vai: PostgREST = truy cập trực tiếp tới bảng (đã RLS); custom API = orchestration, gọi Supabase bên trong. Tránh trùng lặp endpoint cùng một nghiệp vụ (chọn một kênh).
  4. Auth: Cả hai đều nhận JWT; custom API verify JWT (bài 5) rồi gọi Supabase với JWT (pass-through) hoặc service role (khi cần bypass RLS có kiểm soát).

Quy ước: Tách rõ “API public” (frontend gọi) và “data layer” (Supabase); custom API là lớp trên data layer, không lộ chi tiết schema nếu không cần.

Sample code

Call PostgREST from frontend

const { data } = await supabase
  .from('conversations')
  .select('id, title, created_at')
  .eq('user_id', userId)
  .order('updated_at', { ascending: false })
  .limit(20);

Custom API (Express): aggregate endpoint

// GET /api/me/conversations-summary
app.get('/api/me/conversations-summary', async (req, res) => {
  const userId = getUserIdFromRequest(req);
  if (!userId) return res.status(401).json({ error: 'Unauthorized' });
  const { data, error } = await supabaseAdmin
    .from('conversations')
    .select('id, title, updated_at')
    .eq('user_id', userId)
    .order('updated_at', { ascending: false })
    .limit(20);
  if (error) return res.status(500).json({ error: error.message });
  res.json(data);
});

supabaseAdmin dùng service role; hoặc dùng JWT của user (pass-through) để RLS vẫn áp dụng.

Apply in your architecture

  • API contract: PostgREST contract = schema + RLS; custom API contract = endpoint + request/response. Keep consistent (names, JSON format, error codes) so clients and team can integrate easily.
  • Tách biệt consumer và data: Frontend có thể gọi PostgREST trực tiếp (đơn giản) hoặc chỉ gọi custom API (ẩn schema). Backend custom đóng vai “orchestrator” khi cần, không nhân bản toàn bộ CRUD đã có sẵn ở PostgREST.
  • Một nguồn sự thật: Dữ liệu vẫn nằm trong Supabase; PostgREST và custom API cùng đọc/ghi một DB, tránh đồng bộ hai nguồn.

Kết

PostgREST đủ cho CRUD và truy vấn đơn giản; custom API dùng khi có logic phức tạp hoặc cần ẩn schema. Bài tiếp sẽ nói Realtime và Edge Functions.

Bài tiếp: 09 — Realtime và Edge Functions

Đọc thêm: Supabase — PostgREST API

LDK

Le Duy Khuong

AI Transformation & Digital Strategy. Writing about agentic systems, engineering leadership, and building in public.