Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 14 — GraphQL vs REST — Khi nào chọn gì?

Technical BA Masterclass Bài 14/60

Mở đầu — vì sao bài này quan trọng

Trong vai trò Technical BA, bạn sẽ thường xuyên đứng giữa hai phe trong các cuộc họp thiết kế kỹ thuật: một bên là đội backend muốn xây API "đơn giản, dễ cache, dễ vận hành", một bên là đội mobile/frontend than phiền "API trả về thừa data, lại phải gọi năm bảy lần mới đủ một màn hình". Câu hỏi "Mình dùng REST hay GraphQL?" gần như chắc chắn sẽ rơi vào bàn họp mà bạn tham gia, đặc biệt khi công ty đang xây sản phẩm mới hoặc làm lại hệ thống cũ.

Nhiều BA tránh né câu hỏi này vì nghĩ đó là quyết định thuần kỹ thuật của kiến trúc sư. Đó là một sai lầm. Lựa chọn REST hay GraphQL ảnh hưởng trực tiếp đến trải nghiệm người dùng (tốc độ tải màn hình), chi phí băng thông (rất quan trọng với app mobile tại Việt Nam nơi nhiều người dùng 3G/4G yếu), tốc độ phát triển tính năng, và cả khả năng bảo mật. Một Technical BA hiểu bản chất hai cách tiếp cận này sẽ viết được requirement chính xác hơn, đặt câu hỏi đúng chỗ trong refinement, và giúp team tránh chọn nhầm công nghệ — một quyết định mà sửa lại sau 6 tháng có thể tốn hàng trăm giờ công.

Bài này không yêu cầu bạn tự code GraphQL. Mục tiêu là giúp bạn hiểu đủ sâu để tham gia quyết định, viết spec, và đánh giá đánh đổi (trade-off) một cách tự tin.

Khái niệm cốt lõi

Cả REST và GraphQL đều là cách để client (app, web) lấy và gửi dữ liệu tới server qua HTTP. Khác biệt nằm ở triết lý tổ chức.

REST — tư duy theo "tài nguyên"

REST (Representational State Transfer) tổ chức API quanh khái niệm resource (tài nguyên), mỗi resource có một URL cố định. Ví dụ trong một app thương mại điện tử:

  • GET /api/products/123 — lấy thông tin sản phẩm 123
  • GET /api/products/123/reviews — lấy đánh giá của sản phẩm 123
  • GET /api/users/45/orders — lấy đơn hàng của user 45
Ba đặc điểm quan trọng của REST mà BA cần nhớ:

  • Mỗi endpoint trả về một "hình dạng" (shape) cố định. Khi bạn gọi GET /api/products/123, server quyết định trả về những trường gì — tên, giá, mô tả, hình ảnh, tồn kho... Client nhận hết, dù màn hình chỉ cần tên và giá.
  • Dữ liệu phức tạp cần nhiều lượt gọi (round-trip). Để hiển thị một trang chi tiết sản phẩm gồm thông tin sản phẩm + đánh giá + sản phẩm liên quan, app phải gọi 3 endpoint khác nhau. Đây gọi là vấn đề under-fetching — một lần gọi không đủ.
  • Cache HTTP gần như miễn phí. Vì mỗi URL là cố định và phần lớn là GET, các tầng hạ tầng như CDN, trình duyệt, proxy có thể cache response theo URL một cách tự nhiên. Đây là lợi thế cực lớn của REST mà nhiều người quên.
REST cũng dễ gặp over-fetching — trả về thừa dữ liệu. App mobile chỉ cần tên và avatar của user nhưng endpoint /api/users/45 trả về cả số điện thoại, địa chỉ, lịch sử đăng nhập... tốn băng thông vô ích.

GraphQL — tư duy theo "câu truy vấn"

GraphQL đảo ngược quyền kiểm soát: thay vì server quyết định trả về gì, client mô tả chính xác dữ liệu mình cần và server trả về đúng như vậy. Toàn bộ API chỉ phơi bày qua một endpoint duy nhất, thường là POST /graphql.

Client gửi một query như sau:

query {
  product(id: 123) {
    name
    price
    reviews(first: 3) {
      rating
      comment
    }
    relatedProducts {
      name
      price
    }
  }
}

Server trả về đúng cấu trúc đó — không thừa, không thiếu — trong một lượt gọi duy nhất. GraphQL giải quyết được cả over-fetching (chỉ lấy trường cần) lẫn under-fetching (gộp nhiều resource vào một query).

Ba điểm BA cần nắm:

  • Một endpoint, schema mạnh. GraphQL có một schema mô tả toàn bộ kiểu dữ liệu và quan hệ. Schema này vừa là tài liệu sống vừa là hợp đồng giữa frontend và backend — rất hữu ích cho việc viết spec.
  • Linh hoạt cho client. Đội mobile và đội web có thể cùng dùng một API mà query những trường khác nhau, không cần backend làm endpoint riêng cho từng màn hình.
  • Đánh đổi: mất cache HTTP native và phức tạp hơn ở backend. Vì mọi thứ là POST tới một URL, CDN/trình duyệt không thể cache theo URL như REST. Bù lại, GraphQL có rủi ro về hiệu năng (query lồng nhau quá sâu) và bài toán "N+1 query" xuống database mà backend phải xử lý.

Bảng so sánh nhanh để BA ghi nhớ

Tiêu chíRESTGraphQL
Số endpointNhiều, theo resourceMột (/graphql)
Hình dạng responseCố định, server quyếtLinh hoạt, client quyết
Over/Under-fetchingDễ gặpHạn chế tốt
Cache HTTPNative, mạnhPhải tự xây ở tầng app
Đường cong họcThấpCao hơn
Phù hợp khiResource rõ ràng, cần cacheClient đa dạng, data quan hệ phức tạp

Tình huống thực tế

Ví dụ 1 — Sàn TMĐT giả định "ChợViet" chuyển sang GraphQL cho app mobile

ChợViet có app mobile với màn hình trang chủ phức tạp: banner khuyến mãi, danh mục, sản phẩm gợi ý, flash sale, và thông tin ví của user. Với REST, app phải gọi 6 endpoint khác nhau mỗi lần mở app. Đo đạc cho thấy thời gian tải trang chủ trên mạng 4G yếu ở các tỉnh trung bình 2,8 giây, và mỗi lần mở app tốn khoảng 420 KB dữ liệu (nhiều trường thừa).

Team thử nghiệm gộp toàn bộ trang chủ thành một GraphQL query duy nhất, chỉ lấy đúng trường cần hiển thị. Kết quả: thời gian tải giảm còn 1,5 giây, dung lượng giảm còn 180 KB — tiết kiệm hơn 55% băng thông. Với một app có 2 triệu lượt mở mỗi ngày, đây là khoản tiết kiệm chi phí băng thông và cải thiện trải nghiệm rất đáng kể.

Bài học rút ra: GraphQL tỏa sáng khi client cần ghép nhiều mảnh dữ liệu cho một màn hình và khi băng thông là yếu tố sống còn — đúng bối cảnh người dùng mobile Việt Nam. BA nên đưa "số lượng round-trip mỗi màn hình" và "dung lượng payload" thành tiêu chí đánh giá trong NFR, chứ không quyết định cảm tính.

Ví dụ 2 — Ngân hàng "VPB-Digital" giữ REST cho cổng thanh toán

Một mảng của ngân hàng giả định VPB-Digital xây cổng API thanh toán cho đối tác bên thứ ba (ví điện tử, sàn TMĐT tích hợp). Đội kiến trúc ban đầu muốn dùng GraphQL vì "linh hoạt và hiện đại". BA trong dự án đặt vài câu hỏi quan trọng trong buổi review:

  • Đối tác bên ngoài cần gì? Họ cần endpoint đơn giản, ổn định, dễ tích hợp, và họ quen với REST.
  • Yêu cầu bảo mật và kiểm toán? Mỗi giao dịch phải log rõ ràng theo từng endpoint, dễ áp rate-limiting riêng cho POST /payments so với GET /transactions.
  • Cache? Tra cứu trạng thái giao dịch (GET /transactions/{id}) có thể cache ở mức nhất định để giảm tải.
Kết luận: REST phù hợp hơn cho public API hướng đối tác. Với GraphQL, việc áp rate-limit và phân tích chi phí từng query phức tạp hơn nhiều (một query có thể nhẹ hoặc rất nặng tùy độ sâu), gây khó cho hệ thống tính phí và bảo vệ chống lạm dụng.

Bài học rút ra: Không phải cứ mới là tốt. Với API công khai cho bên thứ ba, REST thường an toàn và dễ quản trị hơn. BA cần nhận diện ai là người tiêu thụ API (internal team hay external partner) trước khi chốt phương án.

Ví dụ 3 — Grab dùng mô hình lai (hybrid)

Trong thực tế, các công ty lớn ở Đông Nam Á như Grab không chọn một-chọi-một. Một mô hình phổ biến là dùng GraphQL ở tầng BFF (Backend For Frontend) — tức một lớp GraphQL phục vụ app người dùng, đứng trước hàng trăm microservice nội bộ vẫn giao tiếp với nhau bằng REST hoặc gRPC. App mobile gọi GraphQL để lấy gọn dữ liệu cho một màn hình đặt xe (vị trí tài xế, giá ước tính, phương thức thanh toán), còn bên dưới lớp GraphQL gọi tới các service REST riêng lẻ để tổng hợp.

Bài học rút ra: REST vs GraphQL không phải lựa chọn loại trừ. Câu hỏi đúng thường là "dùng cái gì ở tầng nào?". BA cần hiểu kiến trúc nhiều tầng để viết requirement đúng ngữ cảnh — GraphQL cho trải nghiệm client, REST/gRPC cho giao tiếp nội bộ.

Hướng dẫn từng bước

Khi đứng trước quyết định REST hay GraphQL cho một dự án, BA có thể đi theo trình tự sau:

  • Xác định ai tiêu thụ API. Internal app của chính công ty, hay external partner? Partner bên ngoài thường ưu tiên REST vì đơn giản, ổn định.
  • Đánh giá độ phức tạp của dữ liệu màn hình. Đếm thử mỗi màn hình quan trọng cần bao nhiêu resource. Nếu nhiều màn hình cần ghép 4-5 nguồn dữ liệu khác nhau, GraphQL có lợi thế rõ.
  • Đo nhu cầu linh hoạt của client. Có nhiều loại client (iOS, Android, web, smart TV) cần các tập trường khác nhau không? Nếu có, GraphQL giảm gánh nặng tạo endpoint riêng.
  • Đánh giá tầm quan trọng của cache. Dữ liệu chủ yếu là đọc và ít thay đổi (danh mục, bài viết)? REST + CDN cực mạnh và rẻ. GraphQL phải tự xây cache phức tạp hơn.
  • Cân nhắc năng lực đội ngũ. Team đã quen GraphQL chưa? Có người xử lý được vấn đề N+1, query depth limiting, security chưa? Nếu chưa, chi phí học và rủi ro vận hành phải đưa vào tính toán.
  • Viết yêu cầu phi chức năng (NFR) liên quan. Dù chọn gì, hãy quy định rõ: thời gian phản hồi tối đa, số round-trip mục tiêu, giới hạn payload, chiến lược cache, và (với GraphQL) giới hạn độ sâu query để chống lạm dụng.
  • Cân nhắc mô hình lai. Nhiều dự án không cần chọn một. Đề xuất GraphQL ở tầng client-facing và REST nội bộ nếu phù hợp.

Lỗi thường gặp & mẹo

Lỗi 1 — Chọn GraphQL chỉ vì "nghe hiện đại". Đây là cái bẫy phổ biến nhất. GraphQL mang theo chi phí vận hành: phải xử lý query phức tạp, bảo mật query lồng sâu, mất cache HTTP native. Nếu API của bạn chỉ là vài endpoint CRUD đơn giản, REST nhanh và rẻ hơn nhiều.

Lỗi 2 — Quên rủi ro bảo mật của GraphQL. Vì client tự viết query, một query lồng nhau quá sâu (ví dụ user → bài viết → bình luận → người bình luận → bài viết... lặp lại) có thể làm sập server. BA nên ghi vào spec yêu cầu giới hạn độ sâu query (depth limiting)query cost analysis. Đây là requirement thật, không phải chi tiết kỹ thuật vụn vặt.

Lỗi 3 — Tưởng GraphQL tự động nhanh hơn. GraphQL gọn payload nhưng nếu backend không xử lý tốt, một query có thể bắn ra hàng trăm câu lệnh xuống database (vấn đề N+1). Nhanh hay chậm phụ thuộc cách triển khai, không phải bản thân GraphQL.

Lỗi 4 — Bỏ qua chuyện cache khi định lượng. Với dữ liệu đọc nhiều (read-heavy) như danh mục sản phẩm, lợi thế cache của REST có thể vượt xa lợi ích gọn payload của GraphQL về tổng thể hiệu năng và chi phí.

Mẹo cho BA: Đừng hỏi "REST hay GraphQL?" trong họp. Hãy hỏi cụ thể hơn: "Mỗi màn hình của app cần bao nhiêu lượt gọi? Client của ta có đa dạng không? Dữ liệu này cache được không? API này cho ai dùng?". Trả lời được những câu này thì lựa chọn công nghệ tự lộ ra.

Bài tập thực hành

  • Phân tích màn hình: Lấy một app bạn đang dùng (ví dụ Shopee, MoMo, Tiki). Chọn một màn hình phức tạp và liệt kê những loại dữ liệu nó hiển thị. Ước lượng nếu dùng REST thì cần bao nhiêu endpoint, và viết thử một GraphQL query mô tả đúng dữ liệu màn hình đó cần.
  • Bảng trade-off: Cho một dự án giả định "API nội bộ phục vụ app giao hàng cho shipper", hãy lập bảng so sánh REST vs GraphQL theo 5 tiêu chí: số round-trip, băng thông, cache, độ phức tạp vận hành, bảo mật. Đưa ra khuyến nghị kèm lý do.
  • Viết NFR: Giả sử team chọn GraphQL. Viết 3 yêu cầu phi chức năng liên quan đến hiệu năng và bảo mật (gợi ý: giới hạn độ sâu query, thời gian phản hồi tối đa, chiến lược cache ở tầng app).
  • Tranh luận có cơ sở: Một kiến trúc sư đề xuất dùng GraphQL cho public API bán cho đối tác bên thứ ba. Viết ra 3 câu hỏi bạn sẽ đặt để kiểm chứng quyết định này.

Tóm tắt

REST tổ chức API theo tài nguyên với URL cố định, hình dạng response do server quyết, mạnh về cache HTTP nhưng dễ gặp over-fetching và under-fetching. GraphQL dùng một endpoint, cho phép client mô tả chính xác dữ liệu cần trong một lượt gọi, rất hợp với client đa dạng và dữ liệu quan hệ phức tạp, nhưng đánh đổi bằng mất cache native, độ phức tạp vận hành và rủi ro bảo mật query.

Không có lựa chọn "đúng tuyệt đối". REST hợp với API công khai cho đối tác, dữ liệu đọc nhiều cần cache, và team chuộng sự đơn giản. GraphQL hợp khi client cần ghép nhiều mảnh dữ liệu, băng thông quan trọng (rất đúng với mobile Việt Nam), và team đủ năng lực vận hành. Nhiều công ty lớn dùng mô hình lai: GraphQL ở tầng client-facing, REST/gRPC ở giao tiếp nội bộ.

Vai trò của Technical BA không phải là người code, mà là người đặt đúng câu hỏi — ai dùng API, màn hình cần bao nhiêu lượt gọi, dữ liệu có cache được không, team có đủ năng lực không — rồi biến câu trả lời thành requirement và NFR rõ ràng, giúp team chọn đúng công cụ cho đúng bài toán.