แคมเปญ Flash Sale ยิง Event ทีละตัว จน 429 Too Many Requests ถล่ม: ออกแบบ Batching ให้รอดพีค

สรุปสั้น ๆ
การยิง event เข้า CAPI ทีละตัวทันทีที่เกิดขึ้นเป็นวิธีที่เข้าใจง่ายที่สุด แต่มีเพดานจำนวนคำขอต่อวินาทีที่แต่ละแพลตฟอร์มกำหนดไว้ ถ้าธุรกิจมีช่วงพีคที่ปิดออเดอร์พร้อมกันเยอะ การยิงทีละตัวจะชนเพดานเร็วกว่าที่คาด การรวม event หลายตัวส่งเป็น batch เดียวคือทางออกที่แพลตฟอร์มส่วนใหญ่รองรับอยู่แล้ว
ร้านหนึ่งที่ผมช่วยดูระบบจัดแคมเปญลดราคา 1 ชั่วโมงเที่ยงคืน ทุกครั้งที่แคมเปญเริ่ม ยอดคนทักเข้า LINE พุ่งขึ้นหลายเท่าตัวภายในไม่กี่นาทีแรก ระบบหลังบ้านที่เคยทำงานปกติตลอดทั้งเดือน จู่ ๆ ก็เริ่มได้ response 429 กลับมาจาก Meta รัว ๆ ในช่วง 10 นาทีแรกของแคมเปญ event ที่ยิงไม่ทันเลยตกไปเป็นคิว retry เต็มระบบ
พอไล่ดูโค้ดพบว่า ทุกครั้งที่มีออเดอร์ปิดสำเร็จ ระบบจะยิง HTTP request เข้า CAPI ทันทีหนึ่งคำขอต่อหนึ่ง event ซึ่งใช้ได้ดีตอน traffic ปกติที่มีออเดอร์ห่าง ๆ กัน แต่พอมีคนปิดออเดอร์พร้อมกันหลายสิบรายการภายในไม่กี่วินาที จำนวนคำขอต่อวินาทีก็พุ่งเกินเพดานที่ Meta อนุญาตสำหรับบัญชีขนาดนั้น
ปัญหานี้แก้ได้ไม่ยากถ้ารู้ว่าแพลตฟอร์มโฆษณาใหญ่ทุกเจ้ามี Batch API ที่รองรับการส่ง event หลายตัวในคำขอ HTTP เดียว ซึ่งช่วยลดจำนวนคำขอทั้งหมดลงได้มาก แต่การใช้ batching ให้ถูกวิธีก็มีรายละเอียดที่ต้องเข้าใจ ไม่ใช่แค่รวม event มัดเป็นก้อนแล้วส่งไปเฉย ๆ
ทำไมยิงทีละ event ถึงชนเพดานเร็วกว่าที่คิด
เพดาน rate limit ของแพลตฟอร์มโฆษณาส่วนใหญ่นับจาก ‘จำนวนคำขอ’ ไม่ใช่ ‘จำนวน event’ ถ้าระบบยิงหนึ่งคำขอต่อหนึ่ง event เพดานคำขอกับเพดาน event จะเท่ากันโดยปริยาย นั่นแปลว่าธุรกิจที่มีช่วงพีคจริง เช่น แคมเปญลดราคาจำกัดเวลา หรือช่วงเทศกาลที่คนสั่งซื้อพร้อมกันเยอะ จะเจอเพดานนี้เร็วกว่าที่คาดไว้มาก แม้ยอดขายเฉลี่ยทั้งวันจะยังห่างจากเพดานรายวันอยู่มาก
จุดที่ทำให้ปัญหานี้ซ่อนอยู่นานคือ ตอนทดสอบระบบมักทดสอบด้วย traffic เบา ๆ ทีละ event ซึ่งไม่มีวันเจอปัญหานี้เลย มันจะโผล่มาเฉพาะตอนที่มี traffic กระจุกตัวจริง ๆ ซึ่งมักเป็นวันที่สำคัญที่สุดสำหรับธุรกิจพอดี เหมือนกับปัญหา queue ที่มักเกิดตอนพีคเช่นกัน
Batch API ทำงานยังไง และรวม event ได้กี่ตัวต่อคำขอ
หลักการของ Batch API คือแทนที่จะยิง HTTP request แยกต่างหากทีละ event ระบบจะสะสม event หลายตัวไว้ในหน่วยความจำหรือ queue ชั่วครู่ แล้วรวมส่งเป็น array เดียวในคำขอเดียว แต่ละแพลตฟอร์มกำหนดจำนวน event สูงสุดต่อ batch ไว้ต่างกัน โดยทั่วไปอยู่ในหลักสิบถึงหลักพัน event ต่อคำขอ ขึ้นอยู่กับสเปกของแต่ละเจ้า
ข้อดีที่ชัดเจนคือ จำนวนคำขอทั้งหมดลดลงมาก จาก 100 event ที่เคยต้องยิง 100 คำขอ อาจเหลือแค่ 2-3 คำขอถ้ารวมเป็น batch ขนาดใหญ่ ซึ่งทำให้ปริมาณคำขออยู่ห่างจากเพดาน rate limit ได้มากขึ้นมาก แม้ปริมาณ event รวมยังเท่าเดิมก็ตาม
เพดาน rate limit และขนาด batch ของแต่ละแพลตฟอร์ม (ตัวอย่างกรอบคร่าว ๆ)
| แพลตฟอร์ม | ลักษณะเพดาน | จุดที่ต้องระวัง |
|---|---|---|
| Meta CAPI | จำกัดตามจำนวนคำขอต่อชั่วโมงต่อ pixel/dataset | ขนาด batch สูงสุดต่อคำขอมีจำกัด ต้องเช็กสเปกล่าสุดก่อนตั้งค่า |
| Google Enhanced Conversions | จำกัดตามโควตาระดับบัญชีโฆษณา | การอัปโหลดแบบ batch ผ่าน Google Ads API ต้องผ่านการยืนยันสิทธิ์แยกต่างหาก |
| TikTok Events API | จำกัดตามจำนวนคำขอต่อวินาทีต่อ pixel | batch ขนาดใหญ่เกินไปอาจทำให้ทั้ง batch ถูกปฏิเสธหาก event เดียวใน batch ผิด format |
ข้อแลกเปลี่ยนของการรอสะสม batch: latency กับ throughput
- รอสะสมนานเกินไป — ลด throughput ปัญหาคำขอได้ดี แต่ event แต่ละตัวจะถึงปลายทางช้าลง ซึ่งอาจกระทบ algorithm การเรียนรู้ของแพลตฟอร์มที่ชอบข้อมูลใหม่ ๆ
- สะสมสั้นเกินไป — event ถึงปลายทางเร็ว แต่ batch แต่ละก้อนมีขนาดเล็ก ไม่ช่วยลดจำนวนคำขอมากเท่าที่ควร โดยเฉพาะตอน traffic น้อย
- ใช้ time window ผสมกับ size threshold — วิธีที่สมดุลกว่าคือส่ง batch ทันทีเมื่อครบจำนวนที่ตั้งไว้ หรือเมื่อครบเวลาสูงสุดที่ยอมรอ (เช่น 3 วินาที) แล้วแต่ว่าอันไหนถึงก่อน
- ตอน traffic พีคจริง — batch จะเต็มไวมาก ทำให้ latency ต่ำโดยธรรมชาติอยู่แล้ว เพราะกว่าจะรอครบเวลาก็มี event มาเต็ม batch ก่อน ปัญหานี้จึงกระทบเฉพาะช่วง traffic น้อยที่ต้องรอนานกว่าจะครบก้อน
ขั้นตอนวาง batching pipeline ให้ทำงานคู่กับ queue ที่มีอยู่
- แยกชั้นรับ event ออกจากชั้นยิง CAPI เหมือนสถาปัตยกรรม queue ปกติ แล้วเพิ่มชั้นสะสม batch ระหว่างสองชั้นนี้ แทนที่ worker จะยิงทันทีที่ดึงงานได้หนึ่งชิ้น
- ตั้งค่า size threshold และ time window ตามลักษณะ traffic จริงของธุรกิจ ไม่ใช่ค่าที่ copy มาจากที่อื่น ธุรกิจที่ traffic กระจุกตัวมากควรตั้ง time window สั้นกว่าธุรกิจที่ traffic สม่ำเสมอ
- จัดการ partial failure ให้ถูกต้อง เพราะบางแพลตฟอร์มตอบกลับเป็นรายการผลลัพธ์แยกทีละ event ใน batch ไม่ใช่สำเร็จหรือล้มเหลวทั้งก้อน ต้องอ่าน response ให้ละเอียดว่า event ไหนสำเร็จ event ไหนต้อง retry
- ทดสอบ batching ด้วยการจำลอง traffic พีคจริงในสภาพแวดล้อมทดสอบก่อนใช้จริง เพื่อดูว่าขนาด batch และ time window ที่ตั้งไว้รองรับได้จริงหรือต้องปรับอีก
สรุป
การยิง CAPI ทีละ event เป็นจุดเริ่มต้นที่เข้าใจง่ายและใช้ได้ดีตอน traffic ยังน้อย แต่ธุรกิจที่มีแคมเปญพีคจริงจะเจอเพดาน rate limit เร็วกว่าที่คาดเสมอ การวาง batching ไว้ล่วงหน้าเป็นการเตรียมพร้อมสำหรับวันที่แคมเปญประสบความสำเร็จเกินคาด ไม่ใช่ปัญหาที่ควรรอให้เกิดก่อนแล้วค่อยแก้
จุดที่ควรจำไว้คือ batching ไม่ใช่แค่การมัด event รวมกันแล้วส่ง แต่ต้องออกแบบให้จัดการ partial failure และ time window ให้เหมาะกับลักษณะ traffic ของธุรกิจแต่ละแบบ ไม่มีค่าตั้งต้นตายตัวที่ใช้ได้กับทุกธุรกิจ
- เพดาน rate limit นับจากจำนวนคำขอ ไม่ใช่จำนวน event ธุรกิจที่ traffic กระจุกตัวช่วงพีคจะชนเพดานเร็วกว่าที่คาด
- Batch API รวม event หลายตัวส่งในคำขอเดียว ช่วยลดจำนวนคำขอทั้งหมดลงได้มาก
- ตั้ง size threshold คู่กับ time window และจัดการ partial failure ให้ถูกต้อง ไม่ใช่ตั้งขนาด batch สูงสุดตายตัวโดยไม่คิดถึงความเสี่ยง
คำถามที่พบบ่อย
batching ทำให้ event ถึงปลายทางช้าลงจนกระทบการวัดผลไหม
ช้าลงในระดับวินาทีถึงไม่กี่นาทีตามการตั้งค่า time window ซึ่งแทบไม่กระทบการอ่านผล conversion ปกติ แต่ถ้าตั้ง time window นานเกินไปในธุรกิจที่ต้องการความสดของข้อมูลสูง ควรลด window ให้สั้นลงแม้จะได้ประโยชน์จากการลดคำขอน้อยลงบ้าง
ถ้าธุรกิจ traffic น้อย ยังจำเป็นต้องทำ batching ไหม
ถ้า traffic ทั้งวันยังห่างจากเพดาน rate limit มาก การยิงทีละ event ก็เพียงพอและง่ายกว่าในการดูแลระบบ แนะนำให้เริ่มทำ batching เมื่อเริ่มเห็นสัญญาณ 429 ในช่วงพีค หรือเมื่อธุรกิจวางแผนแคมเปญที่คาดว่าจะมี traffic กระจุกตัวสูง
batch ที่มี event ผิด format ปนอยู่หนึ่งตัว จะทำให้ทั้ง batch ล้มเหลวไหม
ขึ้นอยู่กับแพลตฟอร์ม บางเจ้าประมวลผลแยกทีละ event ใน batch แล้วรายงานผลแยกกัน บางเจ้าอาจปฏิเสธทั้ง batch ถ้ามี event เดียวผิดสเปก ต้องอ่านเอกสารของแต่ละแพลตฟอร์มให้ชัดและมี validation ก่อนใส่ event เข้า batch เพื่อลดความเสี่ยงนี้
batching กับ queue/retry ที่ทำไว้แล้วขัดกันไหม
ไม่ขัดกัน ทำงานคู่กันได้ดี queue ทำหน้าที่รับงานให้เร็วและกันงานหาย ส่วน batching เป็นชั้นที่อยู่ก่อนจะยิงออกจริง ช่วยลดจำนวนคำขอ ถ้า batch ทั้งก้อนล้มเหลว ก็ยังส่งกลับเข้า retry mechanism ของ queue ได้ตามปกติ
ควรตั้งขนาด batch สูงสุดเท่าที่แพลตฟอร์มอนุญาตเลยไหม
ไม่จำเป็นเสมอไป batch ที่ใหญ่เกินไปแม้จะลดจำนวนคำขอได้มาก แต่ก็เพิ่มความเสี่ยงว่าถ้า batch ทั้งก้อนล้มเหลวจะต้อง retry จำนวน event มากในครั้งเดียว ควรเลือกขนาดที่สมดุลระหว่างประสิทธิภาพกับความเสี่ยงของแต่ละธุรกิจ
บทความที่เกี่ยวข้อง


