- GraphQL là gì và khác REST ở điểm cốt lõi nào?
GraphQL là ngôn ngữ truy vấn cho API, trong đó client mô tả chính xác dữ liệu mình cần và server trả về đúng shape đó. REST thì mỗi endpoint có response shape cố định, nên client hoặc bị over-fetching, hoặc phải gọi nhiều lần…
- Schema trong GraphQL là gì và vì sao nó quan trọng?
Schema là contract mô tả mọi kiểu, field và tham số mà client truy vấn được. Cả hai phía dựa vào nó, nên truy vấn sai tên field hay sai kiểu bị từ chối trước khi thực thi, và mọi công cụ codegen, autocomplete trong…
- Query, Mutation và Subscription khác nhau thế nào?
Query là đọc, Mutation là ghi, Subscription là luồng dữ liệu server đẩy về. Về mặt thực thi có một khác biệt quan trọng: các top-level field của mutation chạy tuần tự để thứ tự thay đổi dữ liệu là xác định, còn các field…
- Resolver là gì và nhận vào những tham số nào?
Resolver là hàm trả về giá trị cho một field. Server đi theo shape truy vấn và gọi resolver tương ứng cho từng field, nên một truy vấn lồng nhiều tầng kích hoạt cả một cây lời gọi. Mỗi resolver nhận bốn thứ: giá trị…
- Dấu chấm than trong schema nghĩa là gì và vì sao nên cân nhắc khi dùng?
Dấu chấm than nghĩa là field không bao giờ trả về null. Đây là cam kết mạnh: nếu resolver trả về null cho field đó, lỗi sẽ lan lên field cha gần nhất cho phép null, và có thể xoá cả một nhánh dữ liệu…
- Vì sao nên dùng biến thay vì ghép giá trị thẳng vào chuỗi truy vấn?
Dùng biến thì query document giữ nguyên shape cho mọi giá trị, nên server phân tích và cache được, còn giá trị được kiểm tra kiểu theo schema. Ghép chuỗi tạo ra một truy vấn khác nhau mỗi lần và cho phép người dùng ảnh…
- Fragment dùng để làm gì trong ứng dụng thực tế?
Fragment gom một nhóm field dùng lại được. Trong thực tế, mỗi component tự khai báo dữ liệu mình cần, rồi màn hình ghép các fragment lại thành một truy vấn duy nhất. Đây là pattern quan trọng khi ứng dụng lớn dần: sửa một…
- Phản hồi GraphQL có thể vừa có dữ liệu vừa có lỗi không? Client nên xử lý thế nào?
Có. Phản hồi gồm phần data và mảng errors, nên một truy vấn có thể trả về partial result: nhánh nào lỗi thì null và được ghi vào mảng errors, nhánh khác vẫn có dữ liệu. Hệ quả cho client: không thể chỉ nhìn HTTP…
- Vấn đề N+1 trong GraphQL là gì và giải quyết ra sao?
Truy vấn danh sách 50 bài viết kèm tác giả sinh ra 51 lời gọi database: một lời gọi lấy danh sách, rồi resolver của field tác giả chạy riêng cho từng bài. Cách xử lý chuẩn là DataLoader: hoãn các yêu cầu lẻ trong…
- Normalized cache ở client GraphQL hoạt động thế nào và cần điều kiện gì?
Nó nhận diện object bằng typename + id của record. Nhờ vậy cùng một object xuất hiện trong nhiều truy vấn chỉ được lưu một bản, và cập nhật nó ở một nơi tự phản ánh ở mọi màn hình đang hiển thị. Điều kiện:…
- Vì sao cursor pagination được ưa dùng trong GraphQL?
Cursor trỏ vào một vị trí xác định trong tập kết quả, nên record mới chèn vào không làm lệch trang như phân trang theo số trang. Đổi lại, nhảy thẳng tới trang thứ mười là việc khó. Quy ước phổ biến là Connection pattern:…
- Phân quyền trong GraphQL nên đặt ở tầng nào và vì sao khó hơn REST?
Đặt ở business logic phía sau resolver, nơi biết cả người dùng lẫn record cụ thể. Kiểm tra chỉ ở gateway là chưa đủ vì nó chỉ biết người dùng là ai, không biết họ có quyền xem đúng record đang yêu cầu hay không.…
- Vì sao API GraphQL công khai cần giới hạn Depth và chi phí truy vấn?
Vì client tự quyết định shape truy vấn, một truy vấn lồng sâu qua quan hệ hai chiều có thể tăng khối lượng theo cấp số nhân và làm quá tải server chỉ với một yêu cầu. Ví dụ kinh điển: bài viết có tác…
- Persisted query và allowlist khác nhau thế nào?
Persisted query tự động cho phép server học truy vấn mới khi gặp lần đầu, sau đó client chỉ gửi hash. Mục đích chính là giảm dung lượng gửi lên. Allowlist thì server chỉ chấp nhận các truy vấn đã đăng ký lúc build và…
- Mutation nên trả về gì và thiết kế tham số đầu vào ra sao?
Trả về record vừa thay đổi kèm các field liên quan, để client cập nhật cache và giao diện ngay. Với normalized cache, chỉ cần id và các field đã đổi là mọi màn hình tự cập nhật. Mẫu phổ biến là một kiểu trả…
- GraphQL xử lý việc thay đổi API thế nào khi không đánh số phiên bản?
GraphQL tiến hoá bằng cách thêm field mới và đánh dấu field cũ là không dùng nữa. Client cũ vẫn chạy vì field cũ còn đó, và field cũ chỉ bị gỡ khi không còn ai truy vấn tới. Điều kiện để cách này hoạt…
- Vì sao cache HTTP khó áp dụng cho GraphQL và có cách nào lấy lại?
Vì mọi truy vấn đi qua một địa chỉ duy nhất và thường dùng POST, nên cache trung gian không phân biệt được các truy vấn khác nhau. Bù lại, GraphQL đẩy việc cache về phía client với normalized cache theo object. Cách lấy lại…
- Codegen từ schema đem lại lợi ích gì cho đội client?
Codegen tạo ra kiểu chính xác cho từng truy vấn, nên gõ sai tên field hay dùng sai kiểu bị bắt lúc biên dịch. Kết hợp với kiểm tra schema trong CI, một breaking change sẽ làm hỏng build thay vì hỏng ứng dụng của…
- Khi nào nên dùng subscription và chi phí vận hành của nó là gì?
Subscription hợp với sự kiện không đoán trước và cần đẩy ngay: tin nhắn mới, giá thay đổi, trạng thái đơn hàng. Với dữ liệu đổi đều đặn, hỏi lại theo lịch thường đơn giản và rẻ hơn nhiều. Chi phí vận hành hay bị…
- Interface và union khác nhau thế nào và dùng cho trường hợp nào?
Interface buộc mọi kiểu cài đặt nó phải có chung một tập field, nên truy vấn được các field đó mà không cần biết kiểu cụ thể. Union gom các kiểu không có gì chung, nên phải dùng fragment theo từng kiểu. Chọn theo ngữ…
- Custom scalar dùng để làm gì và có bẫy nào cần tránh?
Custom scalar cho phép kiểm tra và chuẩn hoá định dạng ngay ở tầng schema: giá trị sai bị từ chối trước khi vào resolver, và mọi client nhận cùng một định dạng. Các kiểu hay dùng: ngày giờ, email, URL, số thập phân chính…
- Directive include và skip dùng khi nào?
Chúng bật tắt một phần truy vấn theo giá trị biến, nên cùng một document phục vụ được nhiều trường hợp. Điều này quan trọng với persisted query, vì ở đó số document khác nhau cần giữ ở mức tối thiểu. Directive chia hai nhóm:…
- Validation của mutation nên đặt ở đâu?
Schema lo phần kiểu và tính bắt buộc, còn luật nghiệp vụ nằm ở business logic. Hệ kiểu không diễn tả được các luật như số tiền phải dương, mã giảm giá còn hiệu lực, hay ngày kết thúc phải sau ngày bắt đầu. Cách…
- Rate limit cho API GraphQL nên tính theo gì?
Tính theo chi phí ước lượng của truy vấn, không phải số yêu cầu. Một truy vấn lấy một record và một truy vấn lồng ba tầng qua danh sách nghìn phần tử là hai khối lượng công việc chênh nhau hàng nghìn lần. Cách…
- Cách tiếp cận schema-first và code-first khác nhau thế nào?
Schema-first: viết schema bằng SDL rồi cài đặt resolver theo nó. Code-first: định nghĩa kiểu bằng mã và schema được sinh ra. Khác biệt thật nằm ở chỗ đâu là source of truth của contract và cách các đội phối hợp. Schema trước hợp khi…
- Trạng thái chỉ tồn tại ở giao diện nên đặt ở đâu khi dùng GraphQL?
Đặt ở state của ứng dụng chứ không nhét vào cache GraphQL. Cache được thiết kế cho dữ liệu server với cơ chế làm mới và hết hạn riêng, còn trạng thái giao diện có vòng đời hoàn toàn khác. Ranh giới nên giữ: dữ…
- Theo dõi hiệu năng server GraphQL nên đo ở mức nào?
Đo theo tên truy vấn và theo thời gian resolve từng field. Đo ở mức endpoint là vô nghĩa vì mọi truy vấn dùng chung một địa chỉ, và status code thường là 200 kể cả khi phản hồi chứa lỗi. Các số liệu đáng…
- Test một server GraphQL nên tập trung vào phần nào?
Chạy truy vấn thật qua schema rồi so kết quả, vì cách này phủ cả schema, resolver và business logic đúng như client sẽ gặp. Data source bên dưới thì giả lập để test nhanh và ổn định. Các trường hợp nên phủ ngoài happy…
- Upload file qua GraphQL nên làm thế nào?
Cách chắc chắn nhất là xin presigned URL qua một mutation, tải tệp thẳng lên kho lưu trữ, rồi gọi mutation thứ hai để gắn tệp vào record. Tệp không đi qua server API nên tránh được giới hạn kích thước và tải nặng. Đặc…
- Khi nào nên gửi truy vấn bằng GET thay vì POST?
Dùng GET khi kết hợp với persisted query: địa chỉ trở nên duy nhất theo hash và biến, nên CDN và proxy trung gian cache được. Với truy vấn dài viết thẳng thì POST an toàn hơn vì không vướng giới hạn độ dài địa…
- Federation giải quyết vấn đề gì và khi nào đáng dùng?
- Mutation chạy tuần tự có phải là transaction không?
- Directive trả dữ liệu theo phần giải quyết vấn đề gì?
- Kiểm tra schema trong CI nên chặn những thay đổi nào?
- Hệ multi-tenant dùng GraphQL cần chú ý điều gì nhất?
- Một downstream service chết làm toàn bộ phản hồi thành null. Vì sao và xử lý ra sao?
- Chuyển một hệ thống REST sang GraphQL nên bắt đầu thế nào?
- Vì sao không nên thiết kế schema phản chiếu đúng cấu trúc bảng database?
- Đánh giá sức khoẻ của một API GraphQL đang chạy nên nhìn vào đâu trước?
- Trường hợp nào GraphQL không phải lựa chọn phù hợp?