ข้ามไปยังเนื้อหา

สถาปัตยกรรมของ Supabase

ทุก request ที่เข้ามาที่ auto-generated API ของ Supabase จะไปถึง Postgres พร้อมพก Postgres role ตัวใดตัวหนึ่งเสมอ — anon, authenticated หรือ service_role — และ role นี้แหละคือแกนหลักทางสถาปัตยกรรมที่ทุกอย่างอื่น (Data API, Row Level Security) สร้างต่อยอดขึ้นมา

auto-generated API ของ Supabase authenticate ทุก request หรือไม่ก็ปฏิบัติกับ request นั้นแบบ anonymous อย่างชัดเจน ไม่ว่าจะเป็นแบบไหน request จะไปถึง Postgres ในฐานะหนึ่งในสาม role นี้

  • anon — request ที่ไม่ได้ authenticate ไม่มี user login อยู่
  • authenticated — request จาก user ที่ login แล้ว พก JWT claim มาด้วย รวมถึง auth.uid() สำหรับระบุว่าเป็น user คนไหน
  • service_role — server-side code ที่เชื่อถือได้ role นี้ bypass Row Level Security ทั้งหมด เป็น key ตัวเดียวกับที่คุณเจอในบทก่อนหน้า
-- Inside a Row Level Security policy, this is exactly how you tell roles apart.
create policy "Users can view their own profile"
on public.profiles
for select
to authenticated
using (auth.uid() = id);

PostgREST คือ service ที่แปล HTTP request แบบ GET /rest/v1/profiles?select=* ให้กลายเป็น SQL query จริง แล้วรัน query นั้น ในฐานะ role ที่ request นั้นพกมา จุดนี้สำคัญกว่าที่ดูเผิน ๆ PostgREST ไม่ได้ implement authorization system แยกของตัวเองเลย แต่พึ่งพา access control ของ Postgres ทั้งหมด — permission แบบ grant/revoke ธรรมดา และ policy Row Level Security — เพื่อตัดสินว่า role นั้นทำอะไรได้จริงบ้าง access control อยู่ที่ database ไม่ใช่ที่ API layer ที่อยู่ด้านหน้า

// This client call becomes an HTTP request to PostgREST, executed as
// whatever role the current session carries (anon or authenticated).
const { data, error } = await supabase
.from('profiles')
.select('id, username')
.eq('id', userId);

Auth, Storage และ Realtime เป็น service แยก (process แยก) แต่ไม่มีตัวไหนสร้าง storage layer ของตัวเองขึ้นมาใหม่เลย ทุกตัวสุดท้ายอ่านเขียน Postgres database เดียวกันนี้

  • Auth (GoTrue) จัดการ schema authauth.users, session และ table ที่เกี่ยวข้อง
  • Storage จัดการ metadata table ของตัวเอง (bucket, object, permission) ใน schema storage ตัวไฟล์จริงอยู่ใน object store แต่ access rule เป็น row ใน Postgres
  • Realtime อ่าน write-ahead log (WAL) ของ Postgres เพื่อ stream การเปลี่ยนแปลงของ row นอกเหนือจากการมี broadcast/presence channel แบบ ephemeral ให้ใช้
flowchart LR
  client["Client request (anon / authenticated / service_role)"] --> postgrest["PostgREST"]
  postgrest -->|"executes SQL as that role"| pg[("Postgres
(grants + RLS enforced here)")]
  auth["Auth (GoTrue)"] --> pg
  storage["Storage"] --> pg
  realtime["Realtime (reads WAL)"] --> pg
role ของ request เดินทางผ่าน PostgREST เข้า Postgres service อื่นใช้ database เดียวกัน
request ที่ไม่ได้ authenticate ใช้ Postgres role ไหน
access control ของ auto-generated API ใน Supabase ถูก enforce อยู่ที่ไหนจริง ๆ
server-side code ที่เชื่อถือได้ใช้ role ไหนเพื่อ bypass Row Level Security
Auth, Storage และ Realtime เกี่ยวข้องกับ Postgres database ข้างล่างยังไง