เรื่องราวการปรับปรุงความเร็วที่รับรู้ได้ด้วยการล็อก Vercel Functions ไว้ที่ Tokyo Region — การแก้ปัญหาการเดินทางไปกลับข้ามมหาสมุทรแปซิฟิก

HeatMapX Engineering Team4 min read
  • engineering
  • nextjs
  • performance
  • vercel

สรุปบทความนี้

  • สาเหตุที่แดชบอร์ดช้าคือ "Vercel Functions อยู่ที่สหรัฐอเมริกา ส่วนฐานข้อมูลอยู่ที่โตเกียว" ทำให้ต้องเดินทางข้ามมหาสมุทรแปซิฟิกทุกครั้ง
  • สามารถตรวจสอบว่ารันอยู่ที่รีเจียนใดได้จากเฮดเดอร์การตอบกลับ x-vercel-id
  • ด้วยการล็อกรีเจียนไว้ที่โตเกียวผ่าน regions ใน vercel.json และการทำคิวรีแบบขนาน จากการวัดผลภายในองค์กรพบว่าเวลาลดลงจากหลายวินาทีเหลือประมาณ 0.2 วินาที

นี่คือบันทึกการตรวจสอบความช้าที่รับรู้ได้จาก "การเปลี่ยนหน้าจอแดชบอร์ดใช้เวลาหลายวินาที" การหาสาเหตุที่แท้จริง และการปรับปรุงแก้ไข โดยแยกแยะปัญหาด้วยการวัดผลจริง ไม่ใช่การคาดเดา

อาการและการแยกแยะปัญหา

การเปลี่ยนหน้าจอใช้เวลาประมาณ 3 วินาที เมื่อแยกแยะก่อนว่าอะไรที่ช้ากว่ากันระหว่าง "การตอบสนองเริ่มต้นของเซิร์ฟเวอร์ (TTFB)" กับ "การดึงข้อมูลเนื้อหา" พบว่าการตอบสนองเริ่มต้นนั้นเร็ว แต่การดึงข้อมูลภายในหน้าเพจต่างหากที่ช้า

คิวรีแต่ละตัวเองบนฐานข้อมูลนั้นเร็วมาก ใช้เวลาเพียงไม่กี่มิลลิวินาที แต่โดยรวมกลับช้า จุดที่เราสงสัยคือสถานที่ที่รันโค้ด (รีเจียน)

สาเหตุที่ 1: การเดินทางไปกลับข้ามมหาสมุทรแปซิฟิก

เมื่อดูเฮดเดอร์การตอบกลับ x-vercel-id พบว่าฟังก์ชันถูกรันอยู่ที่รีเจียนฝั่งตะวันออกของสหรัฐอเมริกา (iad1) ในขณะที่ฐานข้อมูล (Supabase) อยู่ที่โตเกียว นั่นหมายความว่าทุกครั้งที่มีการคิวรี จะเกิดการเดินทางไปกลับระหว่างญี่ปุ่นกับสหรัฐอเมริกา

เฮดเดอร์มีลักษณะดังนี้ (ตัวอย่าง)

x-vercel-id: hnd1::iad1   ← 受け口は東京(hnd1)だが、実行は米国(iad1)

หากมีคิวรีหลายครั้ง ก็จะเกิดการเดินทางไปกลับข้ามมหาสมุทรแปซิฟิกทุกครั้ง ทำให้เวลาแฝง (latency) สะสมมากขึ้นเรื่อยๆ

สาเหตุที่ 2: การรอคิวรีแบบต่อเนื่อง (Serial)

อีกสาเหตุหนึ่งคือ หน้าโฮมดึงข้อมูลสรุปหลายรายการแบบต่อเนื่อง (ทีละรายการตามลำดับ) ทำให้ความล่าช้าจากการเดินทางไปกลับสะสมเพิ่มขึ้นตามจำนวนครั้งที่ทำ

มาตรการแก้ไข

ล็อกรีเจียนไว้ที่โตเกียว

เราเพิ่มการระบุรีเจียนใน vercel.json เพื่อให้ฟังก์ชันรันที่โตเกียว (hnd1)

{ "regions": ["hnd1"] }

ด้วยวิธีนี้ x-vercel-id จะกลายเป็น hnd1::hnd1 ทำให้ทั้งฟังก์ชันและฐานข้อมูลอยู่ที่โตเกียวทั้งคู่ ความล่าช้าจากการเดินทางไปกลับจึงหมดไป

ทำคิวรีแบบขนาน

เราเปลี่ยนการดึงข้อมูลสรุปที่เคยรอแบบต่อเนื่องให้เป็นแบบขนานด้วย Promise.all พร้อมทั้งรวมการดึงข้อมูลที่ซ้ำซ้อนให้เหลือเพียงครั้งเดียว

ผลลัพธ์

จากการวัดผลภายในองค์กร เวลาแสดงผลหน้าโฮมลดลงจากหลายวินาทีเหลือประมาณ 0.2 วินาที จุดสำคัญคือการทำให้กระบวนการเองเร็วขึ้นโดยไม่พึ่งพาแคช ข้อมูลที่แสดงยังคงเป็นข้อมูลล่าสุดอยู่เสมอ

บทเรียนที่ได้

  • เมื่อเจอสถานการณ์ "คิวรีเร็ว แต่หน้าจอช้า" อย่ามองแค่ความเร็วของฐานข้อมูล ให้สงสัยระยะทางทางกายภาพระหว่างฟังก์ชันกับฐานข้อมูล (รีเจียน) ด้วย
  • x-vercel-id เป็นเบาะแสที่ตรวจสอบได้ง่ายและทรงพลังในการดูว่ารันอยู่ที่รีเจียนใด
  • ในสภาพแวดล้อมที่มีต้นทุนการเดินทางไปกลับสูง การรอแบบต่อเนื่องจะกลายเป็นปัญหาใหญ่ การทำงานแบบขนานจึงให้ผลลัพธ์ที่ดีมาก

สรุป

ต้นตอที่แท้จริงของความช้าที่รับรู้ได้คือการเดินทางไปกลับระหว่างสหรัฐอเมริกากับโตเกียว ด้วยมาตรการสองอย่างคือการล็อกรีเจียนและการทำงานแบบขนาน เราสามารถปรับปรุงความเร็วที่รับรู้ได้อย่างมากโดยไม่ต้องพึ่งแคชเลย หากคุณรู้สึกว่า SSR หรือแดชบอร์ดของคุณช้า ลองตรวจสอบความสัมพันธ์ระหว่างรีเจียนที่รันโค้ดกับตำแหน่งของฐานข้อมูลดูก่อน

Heatmap จาก Claude Code — เริ่มฟรี

วางแท็ก tracker หนึ่งบรรทัด รับการวิเคราะห์และข้อเสนอ CRO จาก CLI