“BFF vs API Gateway” là một trong những cặp đôi gây nhầm lẫn nhất trong kiến trúc microservices. Hai mẫu thiết kế này trông tương tự nhau trên sơ đồ. Cả hai đều nằm phía trước các dịch vụ của bạn. Cả hai đều nhận yêu cầu từ client và chuyển tiếp đến các backend. Vì vậy, các nhóm giả định rằng chúng là những lựa chọn cạnh tranh, chọn một và cuối cùng nhồi nhét sai trách nhiệm vào đó.
Chúng không phải là đối thủ cạnh tranh. Một Backend for Frontend (BFF) và một API gateway giải quyết các vấn đề khác nhau, thuộc sở hữu của các nhóm khác nhau và rất thường chạy cùng nhau trong cùng một hệ thống. BFF nằm sau hoặc song song với gateway, chứ không phải thay thế nó.
Hướng dẫn này sẽ phân định rõ ràng. Bạn sẽ tìm hiểu từng mẫu thiết kế thực sự là gì, điểm trùng lặp của chúng, khi nào nên sử dụng một hoặc cả hai, và những sai lầm phát sinh từ việc làm mờ ranh giới giữa chúng. Xuyên suốt bài viết, hợp đồng API là yếu tố không đổi: dù yêu cầu có đi qua gateway, BFF, hay cả hai, mỗi lớp đều phải lộ ra một API mà bạn vẫn phải thiết kế, kiểm thử, giả lập và tài liệu hóa.
API Gateway là gì?
Một API gateway là một điểm vào tập trung nằm giữa client và các dịch vụ backend của bạn. Mọi yêu cầu đều đi qua gateway, nơi áp dụng một tập hợp các vấn đề xuyên suốt (cross-cutting concerns) một cách nhất quán trước khi định tuyến cuộc gọi đi.
Những vấn đề đó là giống nhau cho mọi client và mọi dịch vụ:
- Định tuyến (Routing): khớp một đường dẫn đến với dịch vụ thượng nguồn phù hợp.
- Xác thực và ủy quyền (Authentication and authorization): xác thực token, từ chối các người gọi không được ủy quyền.
- Giới hạn tốc độ và điều tiết (Rate limiting and throttling): bảo vệ các backend khỏi quá tải và lạm dụng.
- Khả năng quan sát (Observability): ghi nhật ký yêu cầu, phát ra số liệu, theo dõi các cuộc gọi giữa các dịch vụ.
- Chấm dứt TLS (TLS termination), lưu trữ đệm (caching) và biến đổi yêu cầu (request transformation): xử lý các phần phụ trợ này một lần, tại một nơi.
Đặc điểm nổi bật của gateway là nó có mục đích chung và thuộc sở hữu tập trung. Một nhóm nền tảng hoặc cơ sở hạ tầng vận hành nó, và nó phục vụ tất cả các client một cách bình đẳng. Nó không quan tâm người gọi là ứng dụng di động, SPA web, hay tích hợp đối tác; nó áp dụng cùng một chính sách cho tất cả mọi người.
Điều này làm cho gateway trở thành nơi tự nhiên để đặt các quy tắc toàn tổ chức. Nếu bạn muốn mọi yêu cầu được xác thực theo cùng một cách, hoặc mọi API được giới hạn tốc độ một cách nhất quán, gateway sẽ thực thi điều đó mà không cần mỗi dịch vụ phải triển khai lại logic. Để biết điều này khác với các công cụ nền tảng rộng hơn như thế nào, hãy xem Quản lý API vs API gateway.
Backend for Frontend (BFF) là gì?
Một Backend for Frontend (BFF), được giới thiệu bởi Sam Newman, đảo ngược định hướng. Thay vì một backend đa năng phục vụ mọi client, bạn xây dựng một backend cho mỗi trải nghiệm người dùng. Ứng dụng web có một BFF web. Ứng dụng di động có một BFF di động. Mỗi BFF được tùy chỉnh chính xác cho một frontend. Mẫu thiết kế này phát triển từ công việc microservices, nơi một backend chung phục vụ nhiều client trở thành điểm nghẽn tương tự như một hệ thống nguyên khối (monolith).
Quy tắc ngón tay cái của Newman là “một trải nghiệm, một BFF”. Các frontend khác biệt đáng kể sẽ có BFF riêng; các frontend tương tự (ứng dụng iOS và Android được duy trì bởi cùng một nhóm) có thể chia sẻ một BFF.
Đặc điểm nổi bật ở đây là quyền sở hữu và hình dạng. Một BFF "gắn chặt với một trải nghiệm người dùng cụ thể và thường sẽ được duy trì bởi cùng một nhóm với giao diện người dùng," theo lời của Newman. Nhóm frontend sở hữu BFF của mình. Họ phát triển client và backend của nó cùng nhau, mà không cần chờ đợi một nhóm backend riêng phê duyệt mọi thay đổi.
Vậy một BFF thực sự làm gì? Nó định hình dữ liệu cho một client:
- Tập hợp (Aggregation): một màn hình di động cần dữ liệu từ năm microservices. BFF di động gọi cả năm dịch vụ và trả về một phản hồi tổng hợp, để điện thoại thực hiện một lượt đi và về thay vì năm lượt.
- Cắt bớt và định hình lại (Trimming and reshaping): client di động chỉ cần ba trường trong số bốn mươi. BFF loại bỏ phần còn lại để tiết kiệm băng thông.
- Định dạng riêng cho từng client (Client-specific formatting): ứng dụng máy tính để bàn lấy nhiều trang cùng lúc để hiển thị chế độ xem phong phú; ứng dụng di động lấy một trang để duy trì sự nhẹ nhàng. Mỗi BFF phục vụ mẫu hình của client mình.
BFF là một dạng bộ tổng hợp API có tính cá nhân hóa: nó tổng hợp các cuộc gọi hạ nguồn, nhưng luôn phục vụ một frontend cụ thể chứ không phải là một lớp trung lập, chia sẻ.
Điểm trùng lặp giữa BFF và API Gateway
Sự nhầm lẫn là điều dễ hiểu vì hai mẫu thiết kế này chia sẻ các hành vi bề mặt. Cả hai đều chặn yêu cầu từ client. Cả hai đều có thể định tuyến đến các backend. Cả hai đều có thể gọi nhiều dịch vụ và kết hợp kết quả. Một sơ đồ của cả hai đều trông giống như một hộp giữa client và các dịch vụ.
Sự trùng lặp là có thật nhưng nông cạn. Sự khác biệt nằm ở mục đích và quyền sở hữu:
- Một API gateway tập hợp và định tuyến một cách chung chung, cho tất cả các client, để tập trung hóa chính sách.
- Một BFF tập hợp và định tuyến một cách cụ thể, cho một frontend, để tối ưu hóa trải nghiệm của client đó.
Hướng dẫn của Microsoft nói thẳng thừng về việc công việc nào thuộc về đâu. Các tính năng xuyên suốt như giám sát, ủy quyền và giới hạn tốc độ nên được trừu tượng hóa khỏi BFF và được xử lý riêng bởi các mẫu thiết kế kiểu gateway. BFF chỉ nên chứa logic dành riêng cho client. Đặt xác thực và điều tiết vào một BFF là bạn vừa xây dựng lại một nửa gateway, một cách tồi tệ, và bạn sẽ phải làm lại điều đó trong mỗi BFF bạn viết.
Vì vậy, ranh giới thực tế là đây: nếu một trách nhiệm là giống nhau cho mọi client, nó thuộc về gateway. Nếu nó thay đổi theo từng frontend, nó thuộc về BFF.
BFF và API Gateway hoạt động cùng nhau
Trong các hệ thống microservices thực tế, bạn hiếm khi chỉ chọn một. Bạn chạy cả hai, theo lớp. Gateway nằm ở rìa. Các BFF nằm phía sau nó.
Một luồng yêu cầu điển hình trông như thế này:
- Client di động gửi yêu cầu với token xác thực của nó.
- API gateway xác thực token, thực thi giới hạn tốc độ, ghi nhật ký yêu cầu để quan sát, sau đó định tuyến nó đến BFF di động.
- BFF di động gọi dịch vụ sản phẩm, dịch vụ kho hàng và dịch vụ định giá, tổng hợp kết quả, cắt bớt tải trọng theo những gì màn hình di động cần, và trả về một phản hồi.
- Gateway truyền phản hồi trở lại client.
Kiến trúc tham chiếu của Microsoft cho mẫu thiết kế này thực hiện chính xác điều đó: một cổng quản lý API xử lý ủy quyền, giám sát, lưu trữ đệm và định tuyến, sau đó chuyển tiếp đến các dịch vụ BFF dành riêng cho client chạy dưới dạng các hàm serverless, các hàm này gọi các microservices cơ bản.
Mỗi lớp làm tốt công việc của mình. Gateway sở hữu các chính sách phải đồng nhất. BFF sở hữu hình dạng phải cụ thể. Nhóm frontend gửi các thay đổi cho BFF của họ mà không cần chạm vào cấu hình gateway, và nhóm nền tảng thắt chặt giới hạn tốc độ mà không cần triển khai lại bất kỳ BFF nào.
Mối quan hệ phân lớp này tương tự như cách một gateway cùng tồn tại với các cơ sở hạ tầng khác thay vì thay thế nó. Một gateway không phải là bộ cân bằng tải (API gateway vs bộ cân bằng tải) và cũng không phải là service mesh (service mesh vs API gateway); mỗi cái xử lý một lớp riêng biệt của đường dẫn yêu cầu, và một BFF chỉ đơn giản là một lớp riêng biệt nữa. Đây là cùng một nguyên tắc đằng sau kết nối API-led: giao cho mỗi lớp một công việc rõ ràng và chỉ để nó làm đúng công việc đó.
Bảng quyết định: BFF vs API Gateway
| Câu hỏi | API Gateway | BFF |
|---|---|---|
| Ai sở hữu nó? | Nhóm nền tảng / cơ sở hạ tầng | Nhóm frontend sử dụng nó |
| Phục vụ ai? | Tất cả các client, đồng nhất | Một frontend cụ thể |
| Công việc chính | Các vấn đề xuyên suốt: xác thực, giới hạn tốc độ, định tuyến, khả năng quan sát | Tổng hợp và định hình dữ liệu riêng cho client |
| Bạn chạy bao nhiêu cái? | Thường là một (cho mỗi rìa) | Một cho mỗi trải nghiệm người dùng khác biệt |
| Khớp nối | Lỏng lẻo, không phụ thuộc client | Chặt chẽ, dành riêng cho client theo thiết kế |
| Tần suất thay đổi | Ổn định, được quản lý bởi nền tảng | Nhanh, theo lộ trình của frontend |
| Thuộc về nó | Bất cứ điều gì giống hệt nhau cho mọi client | Bất cứ điều gì độc đáo cho một client |
Hãy xem đây là một câu hỏi định tuyến cho các trách nhiệm. Giống nhau cho tất cả thì đặt vào gateway. Khác nhau cho mỗi frontend thì đặt vào BFF. Khi một trách nhiệm có cả hai (bạn muốn xác thực tập trung nhưng cũng muốn định hình tải trọng theo từng client), đó là tín hiệu để bạn chạy cả hai lớp, chứ không phải chọn một bên.
Khi nào nên sử dụng cái nào
Sử dụng API gateway khi bạn có nhiều dịch vụ và cần một nơi duy nhất, nhất quán để thực thi xác thực, giới hạn tốc độ và định tuyến. Hầu hết mọi hệ thống microservices đều hưởng lợi từ một cái. Nếu bạn có nhiều hơn một vài dịch vụ được tiếp xúc với client, bạn sẽ muốn có một gateway trước bất cứ điều gì khác.
Sử dụng BFF khi các client khác nhau có nhu cầu khác biệt đáng kể từ cùng một backend, và một API đa năng được chia sẻ đã trở thành một điểm nghẽn. Các yếu tố kích hoạt phổ biến, theo hướng dẫn của Microsoft:
- Một backend chung đòi hỏi nhiều nỗ lực để duy trì vì nó phục vụ các frontend cạnh tranh.
- Bạn liên tục tùy chỉnh một backend đa năng để đáp ứng nhiều giao diện.
- Di động và web có nhu cầu về dữ liệu và hiệu suất thực sự khác biệt.
Bỏ qua BFF khi tất cả các giao diện của bạn đưa ra các yêu cầu giống hoặc tương tự, hoặc chỉ một giao diện giao tiếp với backend. Một BFF thêm một bước nhảy mạng, nhiều dịch vụ hơn để triển khai, và có thể là một số trùng lặp mã giữa các BFF. Nếu một API chung duy nhất phục vụ tốt mọi client, BFF là một sự tốn kém không cần thiết. Microsoft lưu ý rằng một lớp GraphQL với các bộ phân giải (resolvers) cho từng frontend cũng có thể loại bỏ nhu cầu về một BFF riêng, vì client yêu cầu chính xác các trường mà họ muốn.
Sử dụng cả hai khi bạn đang chạy microservices ở quy mô lớn: gateway cho chính sách đồng nhất ở rìa, các BFF phía sau nó để định hình theo client. Đây là trạng thái cuối cùng phổ biến, chứ không phải là điều gì đó xa lạ.
Những sai lầm thường gặp
Đặt xác thực và giới hạn tốc độ vào BFF. Đây là lỗi lớn nhất. Các vấn đề xuyên suốt thuộc về gateway. Trùng lặp chúng giữa các BFF và bạn sẽ gặp tình trạng lệch chính sách: BFF di động thực thi một chính sách, BFF web lại thực thi một chính sách khác, và tình hình an ninh của bạn trở nên không nhất quán một cách tình cờ.
Để BFF trở thành một monolith thứ hai. Một BFF được thiết kế để nhỏ gọn và tập trung vào một trải nghiệm. Khi các nhóm chất chồng logic nghiệp vụ chung vào đó, nó lại phát triển thành một backend đa năng và bạn đã tái tạo chính xác điểm nghẽn mà mẫu thiết kế này được tạo ra để loại bỏ.
Sử dụng gateway như một BFF. Một số nhóm thêm các quy tắc biến đổi yêu cầu theo client trực tiếp vào cấu hình gateway để tránh xây dựng một BFF. Điều này hoạt động ở quy mô nhỏ, nhưng gateway thuộc sở hữu tập trung, vì vậy giờ đây nhóm frontend phải gửi yêu cầu (tickets) đến nhóm nền tảng cho mọi chỉnh sửa dành riêng cho client. Bạn đã kết nối sai các nhóm.
Xây dựng BFF khi chỉ có một client. Nếu bạn có một ứng dụng web duy nhất và không có client nào khác trong tương lai gần, một BFF là quá sớm. Hãy triển khai API chung. Thêm BFF khi một client thứ hai, khác biệt thực sự xuất hiện.
Quên hợp đồng. Mọi BFF và mọi tuyến gateway đều lộ ra một API. Mỗi cái đều cần một hợp đồng được định nghĩa rõ ràng, các kiểm thử và tài liệu, giống như bất kỳ API nào khác. Bỏ qua điều này và lớp BFF "mỏng" của bạn sẽ trở thành một hộp đen không có tài liệu mà không ai ngoài nhóm sở hữu có thể tích hợp được. Xem hợp đồng API là gì để biết tại sao điều này quan trọng.
Apidog phù hợp ở đâu
Dù một yêu cầu có đi qua API gateway, BFF, hay cả hai, mỗi lớp đều lộ ra một hợp đồng API. Apidog là nơi bạn thiết kế, kiểm thử, giả lập và tài liệu hóa các hợp đồng đó. Nó không xây dựng, lưu trữ hay thay thế gateway hoặc BFF; nó cung cấp cho bạn một không gian làm việc duy nhất cho các bề mặt API mà chúng lộ ra.

Cụ thể:
- Thiết kế (Design): mô hình hóa phản hồi tổng hợp của BFF hoặc lược đồ điểm cuối được định tuyến của gateway theo hướng lược đồ (schema-first) trong trình thiết kế trực quan, sau đó tạo OpenAPI để cả nhóm frontend và backend của bạn xây dựng dựa trên đó.
- Giả lập (Mock): khởi tạo một giả lập thông minh của BFF để nhóm di động có thể phát triển màn hình của họ trước khi các dịch vụ hạ nguồn của BFF tồn tại. Đây là quy trình làm việc API-first giúp công việc frontend và backend song song trở nên khả thi.
- Kiểm thử (Test): xây dựng các kịch bản kiểm thử tự động truy cập các điểm cuối phía trước gateway chính xác như một client thực, xác thực xác thực, mã trạng thái và hình dạng tải trọng tổng hợp.
- Tài liệu hóa (Document): xuất bản tài liệu tương tác cho mỗi BFF và tuyến gateway để mọi nhóm sử dụng đều biết hợp đồng mà không cần đọc triển khai.
Mẫu thiết kế bạn chọn là một quyết định kiến trúc. Hợp đồng mà mỗi lớp lộ ra là một hằng số. Apidog xử lý hằng số đó, để các BFF và gateway của bạn luôn được thiết kế, kiểm thử, giả lập và tài liệu hóa cho dù bạn kết nối chúng như thế nào.
Dùng thử Apidog miễn phí để thiết kế và giả lập các hợp đồng BFF và gateway của bạn trước khi bạn viết một dòng mã backend nào.
Câu hỏi thường gặp
BFF có phải là một loại API gateway không? Không. Chúng trùng lặp ở chỗ cả hai đều có thể định tuyến và tổng hợp, nhưng BFF thuộc sở hữu của một nhóm frontend và được tùy chỉnh cho một trải nghiệm client, trong khi API gateway thuộc sở hữu tập trung và phục vụ tất cả các client một cách đồng nhất. Một BFF thường nằm phía sau một gateway.
Tôi có thể sử dụng BFF mà không cần API gateway không? Có, nhưng bạn thường không nên làm điều đó ở quy mô lớn. Nếu không có gateway, mỗi BFF phải triển khai lại các vấn đề xuyên suốt như xác thực và giới hạn tốc độ, dẫn đến sự không nhất quán. Gateway tập trung những vấn đề đó để mỗi BFF chỉ xử lý việc định hình dành riêng cho client.
Tôi nên có bao nhiêu BFF? Hãy tuân theo nguyên tắc "một trải nghiệm, một BFF" của Sam Newman. Xây dựng một BFF riêng cho mỗi frontend khác biệt đáng kể. Các client tương tự được duy trì bởi cùng một nhóm, như ứng dụng iOS và Android, có thể chia sẻ một BFF.
BFF có thay thế API gateway của tôi không? Không. Chúng là các lớp bổ trợ cho nhau. Gateway thực thi chính sách đồng nhất ở rìa; BFF định hình dữ liệu cho một client cụ thể phía sau nó. Hầu hết các hệ thống microservices thực tế đều chạy cả hai.
Khi nào tôi không nên xây dựng BFF? Bỏ qua nó khi tất cả các client đưa ra các yêu cầu tương tự, khi chỉ có một client tồn tại, hoặc khi một lớp GraphQL với các bộ phân giải (resolvers) cho từng frontend đã cho phép client lấy chính xác dữ liệu họ cần.
Xác thực và giới hạn tốc độ nên thuộc về BFF hay gateway? Thuộc về gateway. Đây là những vấn đề xuyên suốt cần phải đồng nhất trên tất cả các client. Đặt chúng vào BFF sẽ trùng lặp logic trên mọi BFF và gây ra sự lệch chính sách.
