ทราฟฟิกพุ่งกลางดึกแต่ Cloudflare Workers เชื่อม Supabase Postgres ไว้ทัน แก้ยังไง

สรุปสั้น ๆ
Cloudflare Workers เชื่อมกับ Supabase Postgres และ Auth ได้ผ่าน REST API มาตรฐานของ Supabase (PostgREST) หรือผ่าน HTTP-based driver ที่ออกแบบมาให้ใช้ใน edge runtime โดยเฉพาะ ไม่ใช่ TCP connection แบบตรงที่ Postgres driver ทั่วไปใช้ จุดสำคัญคือต้องเข้าใจว่า Workers ไม่มี connection pool แบบ long-lived เหมือน server ทั่วไป การออกแบบให้ทนต่อ traffic พุ่งกะทันหันต้องอาศัย Hyperdrive หรือ REST layer ที่ Supabase จัดการ connection ให้แทน
Cloudflare Workers กับ Supabase เป็นสองบริการที่มาจากคนละ provider แต่หลายทีมเลือกใช้ร่วมกัน เพราะต้องการ edge network กว้างของ Cloudflare สำหรับรันโค้ด ในขณะที่ยังอยากใช้ Postgres ที่มี Auth, Storage และ Realtime พร้อมใช้ของ Supabase อยู่
ปัญหาที่ทีมมักเจอตอนเริ่มเชื่อมสองบริการนี้เข้าด้วยกันคือ Workers runtime ไม่รองรับ TCP connection แบบตรงไปหา Postgres เหมือนที่ server ทั่วไปทำได้ ทำให้ driver Postgres แบบดั้งเดิมใช้ไม่ได้ตรง ๆ ต้องเปลี่ยนวิธีคิดเรื่องการต่อฐานข้อมูลใหม่ทั้งหมด
บทความนี้จะอธิบายว่าทำไม Workers ต่อ Postgres ตรง ๆ ไม่ได้ มีทางเลือกอะไรบ้างที่ใช้ได้จริง และควรออกแบบระบบยังไงให้รองรับ traffic ที่พุ่งกะทันหันโดยไม่ทำให้ Postgres ล่มเพราะ connection ล้น
ทำไม Workers ต่อ Postgres แบบ TCP ตรง ๆ ไม่ได้
Cloudflare Workers รันบน V8 isolate ที่ไม่มี TCP socket API แบบที่ Node.js มีให้ใช้ตามปกติ ขณะที่ driver Postgres ส่วนใหญ่ เช่น pg หรือ postgres.js ถูกออกแบบมาให้เปิด TCP connection ตรงไปหา database server ทำให้เมื่อนำมารันบน Workers โดยตรงจะพบว่า driver เหล่านี้ใช้งานไม่ได้ตั้งแต่ขั้นตอนเชื่อมต่อ
นี่ไม่ใช่ข้อจำกัดเฉพาะของ Supabase แต่เป็นข้อจำกัดของ Postgres protocol เองที่ออกแบบมาให้สื่อสารผ่าน TCP เป็นหลัก ทุกบริการที่ใช้ Postgres แล้วต้องการรันบน edge runtime แบบ Workers จึงเจอปัญหาเดียวกันหมด ไม่ใช่เฉพาะ Supabase
ทางออกที่ใช้กันจริงมีสองแนวทางหลัก คือใช้ HTTP-based API แทนการต่อ TCP โดยตรง หรือใช้บริการตัวกลางที่แปลง HTTP request จาก Workers ให้กลายเป็น TCP connection ไปหา Postgres แทน ซึ่งเป็นแนวทางที่ Cloudflare Hyperdrive ใช้
ใช้ Supabase REST API (PostgREST) จาก Workers โดยตรง
Supabase มี layer ที่แปลง schema ของ Postgres ให้กลายเป็น REST API อัตโนมัติผ่าน PostgREST ทำให้ Workers สามารถเรียกข้อมูลผ่าน fetch แบบ HTTP ปกติได้เลย โดยไม่ต้องพึ่ง TCP connection ใด ๆ วิธีนี้เข้ากับธรรมชาติของ Workers ได้ดีที่สุด เพราะ fetch เป็น Web API มาตรฐานที่ Workers รองรับเต็มรูปแบบอยู่แล้ว
ข้อดีของแนวทางนี้คือ setup ง่าย ไม่ต้องพึ่ง driver พิเศษ และ Supabase client library เวอร์ชันที่รองรับ edge runtime ก็ใช้กลไกนี้อยู่เบื้องหลัง แต่ข้อจำกัดคือ query ที่ซับซ้อนมาก เช่น raw SQL หลายชั้นหรือ transaction ข้ามหลายตารางพร้อมกัน อาจทำได้ไม่สะดวกเท่าการต่อ Postgres โดยตรง ต้องพึ่งพา RPC function ที่สร้างไว้ล่วงหน้าฝั่ง Postgres แทน
สำหรับงาน Auth ก็เช่นกัน Supabase Auth มี REST endpoint ให้เรียกตรวจสอบหรือ refresh token ได้จาก Workers โดยไม่ต้องพึ่ง driver พิเศษ ทำให้ Workers สามารถตรวจสอบว่า request ที่เข้ามามี JWT ที่ถูกต้องหรือไม่ก่อนดำเนินการต่อได้ง่าย
ใช้ Cloudflare Hyperdrive เมื่อจำเป็นต้อง Query แบบ SQL ตรง ๆ
สำหรับงานที่ต้องการเขียน SQL query ที่ซับซ้อนหรือใช้ ORM ที่คุ้นเคยอยู่แล้ว Cloudflare มีบริการ Hyperdrive ที่ทำหน้าที่เป็นตัวกลาง รับ connection จาก Workers ในรูปแบบที่ edge runtime รองรับ แล้วแปลงเป็น connection จริงไปหา Postgres ฝั่งปลายทาง พร้อมทำ connection pooling ให้ในตัว อ่านรายละเอียดเพิ่มเติมเรื่องการตั้งค่า Hyperdrive ได้ในบทความ Cloudflare Hyperdrive คืออะไร
ข้อดีของแนวทางนี้คือยังเขียน SQL หรือใช้ ORM แบบเดิมได้ ไม่ต้องเปลี่ยนวิธีเขียน query ทั้งหมดไปเป็น REST call แต่ต้องตั้งค่า Hyperdrive ให้ชี้ไปที่ connection string ของ Supabase (แนะนำให้ใช้ pooled connection ของ Supabase เป็นปลายทาง ไม่ใช่ direct connection) เพื่อไม่ให้เกิดปัญหา connection ซ้อนสองชั้นโดยไม่จำเป็น
ข้อควรระวังคือ Hyperdrive เป็นอีกจุดหนึ่งในสถาปัตยกรรมที่ต้องดูแล มีการตั้งค่าและมี failure mode ของตัวเอง ทีมที่เลือกทางนี้ควรเข้าใจว่ากำลังเพิ่ม dependency อีกชั้นเข้าไปในระบบ ไม่ใช่แค่ 'ต่อฐานข้อมูลปกติ' เหมือนตอนรันบน server แบบเดิม
ออกแบบให้ทน Traffic พุ่งกะทันหันได้จริง
จุดแข็งของ Workers คือ scale ขึ้นได้เร็วมากตาม traffic ที่เข้ามา แต่จุดอ่อนที่ตามมาคือ Postgres ฝั่งปลายทางไม่ได้ scale ตามในอัตราเดียวกัน ถ้าไม่มีชั้นป้องกันที่ดี traffic ที่พุ่งกะทันหันอาจทำให้ Postgres ได้รับ request มากเกินกว่าที่รับไหว แม้จะผ่าน REST API หรือ Hyperdrive ที่มี pooling อยู่แล้วก็ตาม
แนวทางที่ช่วยได้คือแยกงานที่ไม่จำเป็นต้องเสร็จทันทีออกจาก request path หลัก เช่นถ้า Workers ต้องบันทึก log หรือ analytics event ทุกครั้งที่มี request ควรส่งเข้า queue แทนการเขียนลง Postgres ตรง ๆ ทุก request อ่านแนวทางการใช้ queue ร่วมกับ Workers เพิ่มเติมได้ในบทความ Cloudflare Queues คืออะไร
อีกแนวทางคือใช้ cache สำหรับข้อมูลที่อ่านบ่อยแต่เปลี่ยนไม่บ่อย เช่นข้อมูล config หรือ product catalog เพื่อลดจำนวน query ที่ยิงไปหา Postgres จริงในช่วง traffic สูง ไม่ใช่พึ่งพา connection pooling เพียงอย่างเดียวในการรับมือกับทุกสถานการณ์
ตัวอย่างสมมติ: รับมือ Traffic พุ่งตอนแคมเปญกลางดึก
ลองดูตัวอย่างสมมติของทีมที่ทำระบบแจ้งเตือนสำหรับแคมเปญ flash sale ซึ่งเปิดขายตอนเที่ยงคืนพอดี (ตัวเลขทั้งหมดเป็นตัวอย่างสมมติเพื่อประกอบการอธิบายวิธีคิด)
ช่วง 5 นาทีแรกหลังเปิดขาย มีผู้ใช้เข้ามาพร้อมกันจำนวนมากกว่าช่วงเวลาปกติหลายสิบเท่า Workers scale ขึ้นรองรับ request ได้ตามที่คาดไว้ แต่ Postgres ที่ใช้ direct connection ผ่าน Hyperdrive แบบไม่มี cache เริ่มมี query ค้างเพิ่มขึ้นเรื่อย ๆ จนบาง request ได้ response ช้ากว่าปกติมาก
ทีมแก้ปัญหาด้วยการเพิ่ม cache layer สำหรับข้อมูลสต๊อกสินค้าที่อ่านบ่อยที่สุด โดยอัปเดต cache ทุกครั้งที่มีการซื้อสำเร็จแทนที่จะ query สต๊อกจาก Postgres ทุก request พร้อมย้าย log การเข้าชมหน้าเพจไปเข้า queue แทนการเขียนลง Postgres ตรง ๆ ผลคือจำนวน query จริงที่ไปถึง Postgres ลดลงมาก ทำให้ response time ในช่วงพีคกลับมาเสถียรกว่าเดิม
บทเรียนจากเคสสมมตินี้คือการมี edge network ที่ scale เร็วอย่าง Workers ไม่ได้แปลว่าฐานข้อมูลปลายทางจะรับไหวโดยอัตโนมัติ ต้องออกแบบชั้น cache และ queue รองรับไว้ล่วงหน้าสำหรับ workload ที่คาดว่าจะมี traffic พุ่งแบบกะทันหัน ไม่ใช่รอให้ปัญหาเกิดแล้วค่อยแก้
ตารางเทียบวิธีเชื่อม Workers กับ Supabase
สรุปให้เห็นภาพรวมของแต่ละแนวทางที่กล่าวถึงข้างต้น
| วิธีเชื่อมต่อ | เหมาะกับงานแบบไหน | ข้อจำกัดหลัก |
|---|---|---|
| Supabase REST API (PostgREST) | query พื้นฐานถึงปานกลาง ต้องการ setup ง่าย | query ซับซ้อนมากต้องพึ่ง RPC function ที่สร้างไว้ล่วงหน้า |
| Cloudflare Hyperdrive | ต้องการเขียน SQL หรือใช้ ORM แบบเดิม | เพิ่ม dependency อีกชั้นที่ต้องดูแลและตั้งค่าเอง |
| Supabase Auth REST endpoint | ตรวจสอบ/refresh JWT จาก Workers | ไม่ใช่ session cookie แบบเดียวกับที่ Next.js ใช้บน Vercel |
| Cache + Queue เสริม | ลด load ที่ยิงไปหา Postgres ช่วง traffic สูง | ต้องออกแบบ invalidation ของ cache ให้ถูกต้อง ไม่งั้นข้อมูลเก่าค้าง |
RLS กับ Anon Key เทียบ Service Role Key เวลาเรียกจาก Workers
อีกจุดที่มักถูกมองข้ามตอนเชื่อม Workers กับ Supabase คือเรื่องสิทธิ์ของ key ที่ใช้เรียก REST API ไม่ใช่แค่เรื่อง connection Supabase ให้ key สองแบบหลักคือ anon key ที่ยังต้องผ่าน Row Level Security ทุกครั้ง กับ service role key ที่ข้าม RLS ทั้งหมด ปัญหาคือใน Workers ซึ่งเป็นโค้ดฝั่งเซิร์ฟเวอร์ที่ไม่มี browser คั่นกลาง นักพัฒนาบางคนเผลอเลือกใช้ service role key เพราะ 'เขียนแล้วรันผ่านง่ายกว่า' โดยไม่ตั้งใจว่าทุก request จาก Workers ตัวนั้นจะข้าม RLS ไปเลย
แนวทางที่ปลอดภัยกว่าคือแยกให้ชัดว่า Workers ตัวไหนทำหน้าที่อะไร ถ้า Workers ตัวนั้นรับ request จากผู้ใช้ปลายทางโดยตรงและควรบังคับใช้สิทธิ์ตามผู้ใช้แต่ละคน ให้ใช้ anon key พร้อมแนบ JWT ของผู้ใช้ที่ผ่านการยืนยันแล้วไปกับทุก request เพื่อให้ RLS ทำงานตามสิทธิ์จริงของคนคนนั้น ส่วน service role key ควรเก็บไว้เฉพาะ Workers ที่ทำงานเบื้องหลังแบบไม่มีผู้ใช้ปลายทางเกี่ยวข้องโดยตรง เช่นงาน sync ข้อมูลตามตารางเวลา และต้องเก็บผ่าน Workers secret binding เท่านั้น ไม่ฝังไว้ในโค้ดที่ commit ขึ้น repository
จุดที่อันตรายกว่าปกติคือ Workers ไม่มีขั้นตอน build ที่แยก client bundle ออกจาก server code แบบ Next.js บาง config เพราะทั้งไฟล์รันเป็นเซิร์ฟเวอร์เดียวกันหมด ทำให้บางทีมเข้าใจผิดว่า key ไหนก็ปลอดภัยเท่ากันเพราะไม่มีฝั่ง client ที่มองเห็นได้ แต่ถ้า Worker ตัวนั้นถูกเรียกใช้แบบเปิดสาธารณะโดยไม่มีการตรวจ JWT ก่อน การใช้ service role key ในเส้นทางนั้นเท่ากับเปิดให้ใครก็ตามที่รู้ endpoint เขียนหรืออ่านข้อมูลข้าม RLS ได้ทั้งหมด ควรทดสอบเฉพาะเจาะจงว่าแต่ละ route ของ Worker บังคับตรวจ JWT ก่อนแตะ service role key จริงหรือไม่ ไม่ใช่แค่เชื่อว่า 'อยู่ฝั่ง server แล้วปลอดภัยเสมอ' อ่านเรื่องการแบ่งขอบเขต backend logic ระหว่าง Vercel กับ Supabase Edge Functions เพิ่มเติมได้ในบทความ Vercel กับ Supabase Edge Functions แบ่ง Backend Logic ซึ่งใช้หลักการแยกสิทธิ์แบบเดียวกัน
ทดสอบ Local Dev กับพฤติกรรมจริงตอน Deploy ต่างกันตรงไหน
เครื่องมือสำหรับรัน Workers ในเครื่องช่วยจำลอง runtime ได้ใกล้เคียงของจริงมาก แต่มีความต่างสำคัญที่ทำให้ผลทดสอบใน local ไม่ได้สะท้อนพฤติกรรมตอน deploy จริงเสมอไป โดยเฉพาะเรื่องเส้นทางเครือข่ายไปหา Supabase ตอนรัน local เครื่องนักพัฒนามัก request Supabase ผ่านอินเทอร์เน็ตทั่วไปจากจุดเดียว ขณะที่ตอน deploy จริง request จะกระจายออกจากหลาย edge location ทั่วโลกพร้อมกัน ทำให้ latency และ pattern ของ connection ที่ Postgres เห็นต่างจากตอนทดสอบในเครื่องพอสมควร
อีกจุดที่มักทำให้ทีมเข้าใจผิดคือเรื่อง secret และ environment variable Workers แยกการตั้งค่าสำหรับ local dev กับ production ออกจากกันชัดเจน ค่าที่ตั้งไว้ในไฟล์ config สำหรับรัน local ไม่ได้ถูกส่งขึ้นไปที่ production โดยอัตโนมัติ ต้องตั้ง secret ของ production แยกต่างหากทุกครั้ง ทีมที่ลืมขั้นตอนนี้มักเจออาการ Worker รันได้ปกติตอน dev แต่พอ deploy จริงกลับ error ทันทีเพราะหา key หรือ connection string ไม่เจอ ซึ่งเป็นคนละสาเหตุกับปัญหาเรื่อง RLS หรือ connection pool ที่กล่าวถึงก่อนหน้า
พฤติกรรมที่จำลองในเครื่องได้ยากที่สุดคือเรื่อง cold start และการจัดสรร isolate ใหม่ของ Workers ตอน local dev เครื่องเดียวมักรัน instance เดียวต่อเนื่อง ไม่มีการสร้างหรือทำลาย isolate ตามจังหวะ traffic แบบที่เกิดขึ้นจริงบน edge network เมื่อกระจาย request ไปหลาย region ทำให้ปัญหาเช่น cache ในหน่วยความจำของ Worker ที่หายไปตอนมี isolate ใหม่ถูกสร้างขึ้นแทนตัวเก่า จะไม่โผล่ให้เห็นตอนทดสอบในเครื่องเลย ต้องอาศัยการทดสอบบน preview environment จริงหรือ staging ที่ deploy ขึ้น edge จริงก่อนเชื่อว่าโค้ดพร้อมใช้งาน ไม่ใช่เชื่อผลจาก local dev เพียงอย่างเดียว แนวทางการทำ proof of concept ก่อนย้ายทั้งระบบที่อธิบายไว้ในบทความ Deploy Next.js บน Cloudflare Workers ใช้หลักการเดียวกันกับการทดสอบ Supabase ผ่าน Workers
ทำแบบนี้แล้วพัง เพราะอะไร
ข้อผิดพลาดที่พบบ่อยเมื่อเชื่อม Cloudflare Workers กับ Supabase โดยไม่เข้าใจข้อจำกัดของ edge runtime
- ใช้ Postgres driver แบบ TCP ตรง ๆ บน Workers — พังตั้งแต่ขั้นตอนเชื่อมต่อเพราะ Workers ไม่มี TCP socket API แบบที่ driver เหล่านั้นต้องการ
- ใช้ direct connection ของ Postgres เป็นปลายทางของ Hyperdrive — แทนที่จะใช้ pooled connection ทำให้เกิด connection ซ้อนสองชั้นโดยไม่จำเป็น
- เขียน log หรือ analytics event ลง Postgres ตรง ๆ ทุก request — ทำให้ช่วง traffic สูง Postgres ต้องรับภาระที่ไม่จำเป็นแทนที่จะโฟกัสกับ query ที่สำคัญจริง
- ไม่มี cache สำหรับข้อมูลที่อ่านบ่อยแต่เปลี่ยนไม่บ่อย — ทำให้ทุก request ต้อง query Postgres ซ้ำโดยไม่จำเป็น เพิ่มความเสี่ยงเมื่อ traffic พุ่งกะทันหัน
สรุป
การเชื่อม Cloudflare Workers กับ Supabase ไม่สามารถใช้วิธีต่อ Postgres แบบ TCP ตรงเหมือนที่ทำบน server ทั่วไปได้ ต้องเลือกระหว่าง REST API ของ Supabase เองหรือ Hyperdrive ของ Cloudflare ตามลักษณะ query ที่ต้องการ
สิ่งที่สำคัญไม่แพ้การเลือกวิธีเชื่อมต่อคือการออกแบบให้ทนต่อ traffic ที่พุ่งกะทันหัน เพราะ Workers scale เร็วกว่าที่ Postgres ฝั่งปลายทางจะรับไหวเสมอ การมี cache และ queue รองรับไว้ล่วงหน้าจึงสำคัญพอ ๆ กับการเลือก connection method ที่ถูกต้อง
- Workers ไม่มี TCP socket API ต้องต่อ Postgres ผ่าน REST API หรือ Hyperdrive แทน
- ตั้งค่า Hyperdrive ให้ชี้ไปที่ pooled connection ของ Supabase เสมอ ไม่ใช่ direct connection
- เตรียม cache และ queue รองรับ traffic พุ่งกะทันหันไว้ล่วงหน้า ไม่พึ่งพา pooling เพียงอย่างเดียว
คำถามที่พบบ่อย
ทำไมจึงต้องใช้ REST API แทนการต่อ Postgres ตรง ๆ บน Workers
เพราะ Cloudflare Workers รันบน V8 isolate ที่ไม่มี TCP socket API แบบที่ driver Postgres ทั่วไปต้องการ REST API ที่สื่อสารผ่าน HTTP จึงเข้ากับ Workers ได้ดีกว่า
Hyperdrive กับ Supabase Connection Pooler ทำงานซ้อนกันได้ไหม
ได้ และแนะนำให้ตั้งค่า Hyperdrive ชี้ไปที่ pooled connection ของ Supabase แทน direct connection เพื่อลดความเสี่ยงเรื่อง connection ล้นที่ปลายทาง
ใช้ RPC function ของ Postgres กับ REST API ยากไหม
ต้องเขียน SQL function ไว้ล่วงหน้าฝั่ง Postgres ก่อน แล้วเรียกผ่าน REST endpoint เฉพาะที่ Supabase สร้างให้อัตโนมัติ เหมาะกับ query ที่ซับซ้อนเกินกว่าที่ REST API พื้นฐานจะรองรับได้ตรง ๆ
Workers ตรวจสอบ Supabase Auth token ได้โดยไม่ต้องพึ่ง cookie ไหม
ได้ โดยรับ JWT ที่แนบมากับ request (เช่นผ่าน header) แล้วเรียก Auth REST endpoint หรือตรวจสอบ signature ของ JWT เองตามวิธีที่ Supabase แนะนำ ไม่ต้องพึ่ง cookie แบบที่ Next.js ใช้บน Vercel
ควรใช้ cache แบบไหนคู่กับ Workers และ Supabase
ขึ้นกับลักษณะข้อมูล ข้อมูลที่เปลี่ยนไม่บ่อยอาจใช้ KV ของ Cloudflare เก็บ cache ได้ ส่วนข้อมูลที่ต้องอัปเดตบ่อยควรพิจารณา cache ที่มีกลไก invalidate ชัดเจนแทนการเก็บนานเกินไป
จำเป็นต้องใช้ Hyperdrive เสมอเมื่อเชื่อม Workers กับ Supabase ไหม
ไม่จำเป็น ถ้างานส่วนใหญ่เป็น query พื้นฐานที่ REST API ของ Supabase รองรับได้อยู่แล้ว การเพิ่ม Hyperdrive อาจเป็นความซับซ้อนที่ไม่จำเป็น ควรพิจารณาเฉพาะเมื่อมี query ที่ REST API ทำได้ไม่สะดวกจริง ๆ
อ่านต่อแบบเจาะลึก
วัด Conversion LINE ทุกแบรนด์ รวมศูนย์ที่เดียว
องค์กรที่มีหลายแบรนด์ หลายสาขา หลาย LINE OA — linli รวม Tracking และส่ง Conversion กลับทุกแพลตฟอร์ม พร้อม Custom Limit เริ่มฟรี 14 วัน
ติดต่อทีม Salesบทความที่เกี่ยวข้อง

ตั้ง LINE Webhook บน Supabase Edge Functions ออกแบบตาราง Event ยังไงให้ไม่พังตอนข้อมูลเยอะ

Workers AI กับ AI Search บน Cloudflare เลือกทางไหนตอนสร้าง Chatbot ให้ LINE OA
