นักพัฒนาคนหนึ่งสามารถลดค่าใช้จ่ายในการประมวลผล (compute charges) ของฐานข้อมูลแบบ serverless ของ Neon ลงได้ โดยการขยายช่วงเวลาการ polling ฝั่ง client จาก 30 วินาที เป็น 15 นาที การเว้นระยะที่นานขึ้นช่วยให้ฐานข้อมูลอยู่ในสถานะ idle นานพอที่จะ scale to zero ซึ่งช่วยกำจัด compute credits ที่ต้องเสียไปจากการทำ polling ทุกๆ 30 วินาทีอย่างต่อเนื่อง
Neon คิดค่าบริการตามทุกวินาทีที่ compute engine ทำงาน ในการตั้งค่าแบบ serverless ทั่วไป ทุกคำขอ (request) ไม่ว่าจะเล็กน้อยเพียงใด ก็จะทำให้ engine ยังคงทำงานอยู่เสมอ แดชบอร์ดบนทีวีของผู้เขียนมีการ query ฐานข้อมูลทุกๆ ครึ่งนาที ทั้งที่ข้อมูลที่แสดงนั้นจะเปลี่ยนก็ต่อเมื่อผู้ใช้ทำการ sync ด้วยตนเองหรือมีการเริ่มการถ่ายทอดสดใหม่เท่านั้น รูปแบบดังกล่าวทำให้ compute pool ของ Neon ไม่สามารถเข้าสู่สถานะ zero-state ที่จะหยุดการคิดเงินได้ ส่งผลให้แดชบอร์ดค่าใช้จ่ายของ Vercel พุ่งสูงขึ้นเป็นระยะๆ
ทำไมการ polling แบบเดิมถึงส่งผลกระทบ
- แดชบอร์ดเป็น React component ฝั่ง client ล้วนๆ ดังนั้นแต่ละ instance ของเบราว์เซอร์จึงเรียกใช้งาน Neon โดยตรง
- การคิดราคาของ Neon ผูกกับเวลาการประมวลผลที่ใช้งานจริง (active compute time) ไม่ใช่จำนวนคำขอ ดังนั้นการเรียกใช้งานเพียงครั้งเดียวทุกๆ 30 วินาทีจึงทำให้เกิดค่าใช้จ่ายพื้นฐานอย่างต่อเนื่อง
- การตรวจสอบผ่าน Vercel ของผู้เขียนแสดงให้เห็นความสัมพันธ์ระหว่างปริมาณ traffic และการใช้งาน compute ของ Neon ซึ่งยืนยันว่าการ polling เป็นตัวที่ทำให้ฐานข้อมูลยังคงทำงานอยู่
วิธีแก้ปัญหาที่ไม่ได้ผล
การทำ debounce แบบเร็วๆ (การหน่วงเวลาคำขอหลังจากมีการโต้ตอบของผู้ใช้ครั้งสุดท้าย) ไม่ได้ช่วยอะไร เพราะตัวจับเวลาก็ยังคงทำงานทุกๆ 30 วินาทีอยู่ดี ผมยังได้ลองใช้ Vercel Edge Functions ด้วย แต่ก็ทำให้ระบบมีความซับซ้อนมากเกินไป
วิธีแก้ไขที่ง่ายดาย
การเปลี่ยนแปลงโค้ดเพียงอย่างเดียวที่จำเป็นคือการเปลี่ยนค่า constant ที่กำหนดช่วงเวลาการรีเฟรช:
- จาก 30 วินาที → 5 นาที
- จากนั้น 5 นาที → 15 นาที
ที่ระยะเวลา 15 นาที Neon จะมีเวลาเพียงพอที่จะรับรู้ถึงการไม่มีการใช้งานและทำการ spin down ทรัพยากรการประมวลผลลง แดชบอร์ดก็ยังคงใช้งานได้ตามปกติ: ผู้ใช้ยังคงเห็นข้อมูลล่าสุดเมื่อทำการรีเฟรชด้วยตนเอง และการ polling อัตโนมัติที่เกิดขึ้นเป็นครั้งคราวก็สามารถตรวจพบการถ่ายทอดสดใหม่ได้โดยไม่ต้องมีการรับส่งข้อมูลที่วุ่นวายตลอดเวลา
ทำไมถึงยังควรทำ polling ฝั่ง client?
- ความเรียบง่าย – ไม่ต้องมี serverless functions หรือขั้นตอนการ build เพิ่มเติม
- ความคาดหวังของผู้ใช้ – แดชบอร์ดทำงานเหมือนแอปฝั่ง client อยู่แล้ว การคลิกด้วยตนเองยังคงให้การอัปเดตที่ทันทีทันใด
- ความสอดคล้องกับโมเดลค่าใช้จ่าย – Neon คิดค่าบริการตามวินาทีของการประมวลผล ไม่ใช่ตามจำนวนคำขอ ดังนั้นการลดความถี่จึงช่วยลดค่าใช้จ่ายได้โดยตรง
บทเรียนสำหรับนักพัฒนา serverless
- ปรับความถี่ในการ polling ให้สอดคล้องกับจังหวะการอัปเดตข้อมูลในโลกความเป็นจริง หากชุดข้อมูลมีการเปลี่ยนแปลงเพียงไม่กี่ครั้งต่อชั่วโมง ช่วงเวลา 15 นาทีก็มักจะเพียงพอแล้ว
- การ polling บ่อยเกินไปในสภาพแวดล้อมแบบ serverless คือตัวขับเคลื่อนค่าใช้จ่ายที่ซ่อนอยู่ เพียงแค่คำขอที่เพิ่มขึ้นหนึ่งครั้งต่อนาทีก็สามารถขัดขวางไม่ให้ฐานข้อมูล scale down ได้เลย
- การปรับแต่งการตั้งค่าเพียงเล็กน้อยสามารถสร้างการประหยัดที่มหาศาลได้ โดยไม่ต้องรื้อโครงสร้างสถาปัตยกรรมใหม่
สรุปสั้นๆ คือ: การเปลี่ยนค่า constant เพียงค่าเดียวสามารถเปลี่ยนฐานข้อมูลที่ต้องทำงานตลอดเวลาให้กลายเป็นส่วนประกอบแบบ serverless อย่างแท้จริง ช่วยลดค่าใช้จ่ายในการประมวลผลในขณะที่ยังคงรักษาประโยชน์ของแดชบอร์ดไว้ สำหรับทีมใดก็ตามที่ใช้งาน Neon หรือบริการประมวลผลแบบคิดตามวินาทีที่คล้ายคลึงกัน การกลับไปตรวจสอบช่วงเวลาการ polling คือชัยชนะที่ทำได้ง่ายและคุ้มค่าที่จะทดลองทำตั้งแต่วันนี้
