Skip to content
Tayakorn
System Design Handbook

System Design Handbook

API Styles — REST vs GraphQL

Over-fetching · Under-fetching · Schema · Query Language · ▶ ในคลิป 1:03:11 – 1:23:41

REST ครองโลกมานาน แต่เมื่อแอปฝั่ง client ซับซ้อนขึ้น (โดยเฉพาะมือถือ) จุดอ่อนสองข้อของมันก็ชัดขึ้นเรื่อย ๆ — GraphQL เกิดที่ Facebook เพื่อแก้สองข้อนี้โดยตรง การเข้าใจ "ปัญหาที่ GraphQL แก้" สำคัญกว่าการจำ syntax

6.1 จุดอ่อนของ REST: Over-fetching และ Under-fetching

  • Over-fetching — endpoint คืนข้อมูลตามรูปแบบตายตัว หน้าจอที่ต้องการแค่ "ชื่อกับรูปโปรไฟล์" ก็ได้ object ผู้ใช้มาทั้งก้อน 40 ฟิลด์ เปลืองแบนด์วิดท์โดยเฉพาะบนมือถือ
  • Under-fetching — หน้าจอเดียวต้องการข้อมูลหลายชนิด แต่ REST แยกเป็นคนละ endpoint จึงต้องยิงหลายรอบต่อเนื่อง (ปัญหา N+1 round trips) แต่ละรอบบวก latency เพิ่ม
REST — หน้าโปรไฟล์ต้องยิง 3 รอบMobile AppREST APIGET /users/42ได้มา 40 ฟิลด์ ใช้จริง 2 (over-fetch)GET /users/42/postsGET /users/42/followers3 round trips = latency ×3 (under-fetch)GraphQL — รอบเดียว ระบุเป๊ะMobile App/graphqlquery { user(id:42) {nameavatarUrlposts(first:5){title}followers{count}← ขอเฉพาะที่หน้าจอใช้ตอบครบทุกอย่างใน 1 round trip
FIG 6.1 โจทย์เดียวกัน (หน้าโปรไฟล์): REST ยิง 3 รอบและได้ข้อมูลเกิน ส่วน GraphQL ประกอบทุกอย่างใน query เดียว

6.2 GraphQL ทำงานอย่างไร

GraphQL มี endpoint เดียว (มักเป็น POST /graphql) และทุกอย่างถูกนิยามด้วย schema แบบมี type ชัดเจน — schema คือสัญญาที่ client กับ server แชร์กัน เครื่องมือ (autocomplete, validation, codegen) จึงเก่งมาก ปฏิบัติการมี 3 ชนิด:

  • Query — อ่านข้อมูล (เทียบ GET)
  • Mutation — เปลี่ยนแปลงข้อมูล (เทียบ POST/PUT/DELETE)
  • Subscription — สมัครรับข้อมูล real-time ผ่าน WebSocket

6.3 ราคาที่ GraphQL เรียกเก็บ

ความยืดหยุ่นของ client กลายเป็นภาระของ server:

  • HTTP caching แทบใช้ไม่ได้ — ทุกอย่างเป็น POST ที่ URL เดียว CDN/browser cache ที่ทำงานกับ GET ของ REST ใช้ไม่ได้ตรง ๆ ต้องพึ่ง client-side cache (Apollo/Relay)
  • Query อันตราย — client เขียน query ซ้อนลึกได้ตามใจ (friends { friends { friends } }) อาจถล่ม DB โดยไม่ตั้งใจ — production ต้องมี depth limit / query cost analysis
  • ปัญหา N+1 ย้ายฝั่ง — round trip ฝั่ง client หายไป แต่ resolver ฝั่ง server อาจ query DB ซ้ำซ้อนแทน ต้องใช้ DataLoader (batching) แก้
  • Setup ซับซ้อนกว่า — schema, resolvers, tooling — overkill สำหรับ API เรียบ ๆ

6.4 ตารางเปรียบเทียบ

มิติRESTGraphQL
Endpointหลายตัว ตาม resourceตัวเดียว (/graphql)
รูปร่าง responseserver กำหนดclient กำหนดต่อ query
Round tripsมักหลายรอบต่อหน้าจอรอบเดียว
CachingHTTP/CDN cache ได้เต็มที่ยาก ต้องใช้ client cache เฉพาะทาง
Type safetyต้องเสริมเอง (OpenAPI)มีในตัวผ่าน schema
เส้นโค้งการเรียนรู้ต่ำ ทุกคนรู้จักสูงกว่า ทั้งสองฝั่ง
เหมาะกับpublic API, microservices ภายใน, งาน CRUD ตรงไปตรงมาmobile/SPA ที่หน้าจอซับซ้อน, ทีม frontend หลายทีมใช้ API กลางร่วมกัน

🧭 ตัวเลือกที่สาม: gRPC — สำหรับการคุยกัน ระหว่าง microservices ภายใน ยังมี gRPC — ใช้ Protocol Buffers (binary) บน HTTP/2 เร็วกว่า JSON มาก พร้อม streaming ในตัว ภาพรวมที่พบบ่อยในบริษัทใหญ่: gRPC ภายใน · REST สำหรับ public API · GraphQL เป็นชั้นรวมข้อมูลให้ frontend (API gateway/BFF) — สามตัวอยู่ร่วมกันได้ ไม่ใช่ศึกแย่งบัลลังก์

6.5 เคสจริง — ทำไมบริษัทใหญ่เลือกไม่เหมือนกัน

Facebook (ผู้สร้าง GraphQL) — ปัญหาที่จุดประกายคือแอปมือถือ: ทีม iOS/Android ต้องประกอบหน้าจอ News Feed จากข้อมูลหลายชนิด (โพสต์, คอมเมนต์, reaction, โปรไฟล์) การยิง REST endpoint แยกทีละก้อนทำให้แอปช้าและ over-fetch หนักบนมือถือที่เน็ตไม่เสถียร ทีม Facebook จึงออกแบบภาษา query ที่ให้ client "บอกรูปร่างข้อมูลที่ต้องการ" แล้ว server ประกอบให้ในรอบเดียว ใช้ภายในตั้งแต่ปี 2012 ก่อนเปิดเป็นโอเพนซอร์สในปี 2015

GitHub (ใช้ทั้งสองแบบคู่กัน) — REST API ของ GitHub มีมาตั้งแต่ต้นและยังเป็น API หลักสำหรับงานส่วนใหญ่ ส่วน GraphQL API เปิดเพิ่มปี 2016 เพื่อให้ client ดึงข้อมูลที่เชื่อมโยงกันซับซ้อน (repo + issues + PR + reviewer ในคำขอเดียว) ได้ในรอบเดียวโดยไม่ over/under-fetch — ทุกวันนี้ GitHub เปิดเผยตรง ๆ ว่าฟีเจอร์บางอย่าง (เช่น Discussions, Projects) เข้าถึงได้ผ่าน GraphQL เท่านั้น ขณะที่บางอย่าง (เช่น logs ของ Actions) ผ่าน REST เท่านั้น — เลือกให้ตรงงาน ไม่ใช่เลือกให้ตรงเทรนด์

🧭 บทเรียนจากทั้งสองเคส — ไม่มีใคร "เปลี่ยนมาใช้ GraphQL ทั้งหมด" จริง ๆ แม้แต่ผู้คิดค้นเอง — GraphQL แก้ปัญหาการประกอบข้อมูลซับซ้อนจากหลายแหล่งให้ client ที่มีข้อจำกัด (มือถือ, แบนด์วิดท์) ส่วน REST ยังคุ้มกว่าเวลา endpoint ตรงไปตรงมาและอยากได้ประโยชน์จาก HTTP caching เต็มที่ — คำถามที่ควรถามจึงไม่ใช่ "REST หรือ GraphQL ดีกว่ากัน" แต่เป็น "endpoint ชุดนี้ client ต้องประกอบข้อมูลซับซ้อนแค่ไหน"

สรุปบทที่ 6 — REST เรียบง่าย cache เก่ง — จุดอ่อนคือ over/under-fetching · GraphQL ให้ client เลือกข้อมูลเป๊ะ ๆ ในรอบเดียว — จ่ายด้วย caching ที่ยากและ server ที่ซับซ้อน · เลือกจากรูปร่างของ client: หน้าจอซับซ้อน/มือถือ → GraphQL ได้เปรียบ, public API/CRUD → REST พอและดีกว่า

Read the full book