NguyenHN
← Về trang chủ
Backend

REST vs GraphQL: chọn kiểu API nào cho dự án mới

·4 phút đọc
Chia sẻ:

REST và GraphQL giải quyết cùng một vấn đề (client lấy dữ liệu từ server) theo hai triết lý khác nhau: REST tổ chức API theo resource (mỗi endpoint trả về 1 hình dạng dữ liệu cố định), GraphQL để client tự khai báo chính xác field nào mình cần trong 1 request duy nhất.

Vấn đề over-fetching và under-fetching của REST

Over-fetching: endpoint REST trả về toàn bộ object dù client chỉ cần 2-3 field (ví dụ GET /users/1 trả về cả address, orders, preferences trong khi client chỉ cần name và avatar). Under-fetching: ngược lại, 1 màn hình cần dữ liệu từ nhiều resource khác nhau, buộc client phải gọi nhiều request liên tiếp (N+1 request từ phía client).

// REST — under-fetching: cần 3 request để render 1 màn hình
GET /users/1          → thông tin user
GET /users/1/posts    → danh sách bài viết của user
GET /posts/5/comments → comment của bài viết đầu tiên
// GraphQL — 1 request, client tự khai báo đúng field cần
query {
  user(id: 1) {
    name
    posts {
      title
      comments { text }
    }
  }
}

Cache — điểm REST vẫn thắng rõ ràng

REST tận dụng được cache HTTP chuẩn (CDN, browser cache, reverse proxy) gần như miễn phí, vì mỗi resource có 1 URL cố định (GET /users/1 luôn cùng 1 URL, dễ cache theo URL). GraphQL thường chỉ có 1 endpoint duy nhất (POST /graphql), mọi query đều đi qua cùng 1 URL với body khác nhau — HTTP cache theo URL gần như vô dụng, phải tự xây cache tầng ứng dụng (Apollo Client cache, DataLoader để chống N+1 ở phía resolver).

Độ phức tạp vận hành

Tiêu chíRESTGraphQL
Số endpointNhiều endpoint, mỗi resource 1 (hoặc vài) endpoint1 endpoint duy nhất cho mọi query/mutation
VersioningThường versioning theo URL (/v1/, /v2/)Không cần version — thêm field mới không phá vỡ query cũ
Rate limiting / giám sátDễ áp dụng theo từng endpointKhó hơn — 1 query GraphQL phức tạp có thể tốn tài nguyên như nhiều REST endpoint cộng lại, cần tự tính 'query cost'
File uploadHỗ trợ tự nhiên qua multipart/form-dataKhông có chuẩn chính thức, cần thư viện/convention riêng
Công cụ dành cho FEfetch/axios thuần là đủCần Apollo Client/urql để tận dụng cache, tránh tự quản lý state thủ công

N+1 query — vấn đề kinh điển ở phía server GraphQL

Khi resolver của 1 field (ví dụ comments của mỗi post) tự động query database riêng cho từng object trong danh sách, một query tưởng chừng đơn giản (danh sách 20 bài viết kèm comment) có thể sinh ra 21 query SQL (1 query lấy 20 bài viết + 20 query lấy comment cho từng bài) thay vì gộp lại thành 2 query. Giải pháp tiêu chuẩn là dùng DataLoader để batch và cache các lệnh gọi trong cùng 1 request.

Vậy chọn cái nào

  • Chọn REST khi: API công khai cho bên thứ ba dùng (REST dễ đọc docs, dễ test bằng curl/Postman, cache HTTP hoạt động tốt), hệ thống đơn giản với ít loại client khác nhau, hoặc team chưa có kinh nghiệm vận hành GraphQL (N+1, query cost, schema design).
  • Chọn GraphQL khi: nhiều loại client cùng dùng chung backend nhưng cần hình dạng dữ liệu khác nhau (web, mobile, admin dashboard), UI phức tạp với nhiều nested data mà REST sẽ cần rất nhiều round-trip, hoặc team đã quen với tooling GraphQL (schema-first development, type generation tự động cho FE).
  • Thực tế nhiều hệ thống lớn dùng cả hai: REST cho API công khai/webhook, GraphQL cho tầng BFF (Backend for Frontend) phục vụ riêng cho web/mobile app nội bộ.

Không có lựa chọn nào đúng cho mọi trường hợp — REST tối ưu cho tính đơn giản, khả năng cache, và tính công khai; GraphQL tối ưu cho tính linh hoạt phía client và giảm số round-trip, đánh đổi bằng độ phức tạp vận hành cao hơn ở phía server.