Nguyen Le PhongNguyen Le Phong

API Gateway Patterns

Một góc nhìn thực tế về trách nhiệm của API gateway: routing, authentication boundary, rate limiting, request aggregation, trade-off của backend-for-frontend, failure mode và observability cần có để vận hành edge của hệ thống rõ ràng hơn.

Dấu hiệu đầu tiên thường rất nhỏ. Một buổi sáng debug, một bạn trong team mở network tab và thấy trang customer profile phải gọi mười một API trước khi render xong. Một call lấy identity, một call lấy billing, một call lấy permission, một call lấy feature flag, và vài call khác tồn tại vì mobile app cũ vẫn cần một response shape khác. Chưa có gì sập, nhưng mọi người đều cảm thấy phần rìa của hệ thống bắt đầu ồn.

API gateway thường được đưa vào ở khoảnh khắc đó. Nó cho client một cửa trước duy nhất, thay vì bắt browser, mobile app, partner integration và internal tool tự biết bản đồ của toàn bộ backend service. Dùng cẩn thận, gateway làm mặt ngoài của hệ thống bình tĩnh hơn. Dùng vội, nó trở thành một ứng dụng thứ hai, nơi routing, security, business logic và các bản vá khẩn cấp tụ lại cho tới khi không ai còn chắc logic thật nằm ở đâu.

Trách nhiệm dễ hiểu nhất của gateway là xử lý những việc lặp lại ở edge. Nó route request tới service đúng. Nó enforce authentication và thường khởi đầu một số authorization check. Nó áp dụng rate limit, giới hạn request size, đôi khi thêm rule theo IP hoặc tenant. Nó có thể chuẩn hóa header, gắn correlation ID, terminate TLS, và cho backend một cách thống nhất để biết ai đang gọi. Những việc này hợp lý khi đặt ở gateway vì nếu mỗi service tự làm một kiểu, drift sẽ xuất hiện rất nhanh.

Routing là pattern đầu tiên nhiều team nhìn thấy. Gateway có thể gửi /api/orders tới order service, /api/payments tới payment service, và /api/profile tới identity service mà không lộ tên service nội bộ cho client. Đây không chỉ là tiện lợi. Nó cho team di chuyển service, tách route, hoặc chạy migration phía sau gateway trong khi public contract vẫn ổn định. Kỷ luật nhỏ ở đây là giữ routing rule càng boring và dễ thấy càng tốt. Khi routing table bắt đầu giấu product decision, gateway không còn là bản đồ nữa mà thành mê cung.

Authentication là boundary tiếp theo cần giữ rõ. Gateway là nơi tốt để verify token, từ chối credential hết hạn, và gắn một identity context đáng tin cậy trước khi request đi vào service. Nhưng gateway không nên là nơi duy nhất giữ authorization quan trọng. Gateway có thể nói, caller này là Nguyen, thuộc tenant A, có các claim này. Order service vẫn phải quyết định caller đó có được đọc đúng order này hay không. Cách tách này tránh một sự dễ chịu nguy hiểm: các service bên trong âm thầm giả định rằng mọi request đi qua gateway đều được phép.

Rate limiting cũng là trách nhiệm edge nhìn đơn giản cho tới khi gặp traffic thật. Một limit tốt bảo vệ hệ thống khỏi loop vô tình, scraping, lỗi từ partner, và spike bất ngờ mà không làm người dùng bình thường bị phạt. Đơn vị limit rất quan trọng: theo IP, theo user, theo tenant, theo API key, hoặc theo route. Public search endpoint, payment callback và admin export không nên dùng cùng một rule. Limit tốt cũng cần tự giải thích bằng status code rõ, retry hint rõ, và log cho operator biết key nào đã vượt ngưỡng. Một throttle im lặng chỉ là một outage chậm hơn.

Một số gateway còn làm request aggregation. Thay vì để mobile app gọi năm service để vẽ một dashboard, gateway gọi các service đó và trả về một response đúng hình dạng màn hình. Cách này giảm network chatter và làm client đơn giản hơn, đặc biệt trên kết nối mobile. Trade-off nằm ở ownership. Gateway lúc này biết shape của một product screen, và khi screen đổi, gateway cũng đổi. Vì vậy aggregation thường nên ở gần một client experience cụ thể, không nên thành nơi chung để đặt business rule vốn thuộc về domain service.

Đây là lúc backend-for-frontend cần được bàn một cách bình tĩnh. BFF là một gateway được thiết kế riêng cho một frontend hoặc một nhóm client: web, iOS, Android, partner API, hoặc internal admin. Nó giúp mỗi client nhận response shape mình cần mà không bắt mọi backend service phục vụ mọi presentation concern. Chi phí là có thêm surface để sở hữu. Web BFF và mobile BFF có thể drift về behavior nếu không ai theo dõi contract. Pattern này đáng dùng khi nhu cầu giữa các client thật sự khác nhau. Nó kém hữu ích hơn khi chỉ tạo thêm một layer để vá nhanh vì thay đổi service nghe có vẻ chậm.

Failure mode lớn nhất là để gateway trở thành monolith mới. Ban đầu chỉ là vài đoạn glue vô hại: đổi một header, thêm một fallback, chuyển đổi tạm một field. Sáu tháng sau, pricing rule, permission exception, data join, A/B logic và behavior riêng cho partner đều nằm trong gateway vì đó là nơi nhanh nhất để sửa. Nhìn bên ngoài hệ thống vẫn giống microservices, nhưng product logic thật đã gom lại ở edge layer. Một rule hữu ích là: gateway có thể coordinate và bảo vệ edge; nó không nên là chủ sở hữu của domain truth.

Một failure mode khác là quên rằng gateway giờ nằm trên mọi critical path. Nếu gateway down, mọi service phía sau có thể vẫn khỏe nhưng sản phẩm vẫn coi như down. Timeout, circuit breaker, graceful degradation và safe default rất quan trọng ở đây. Một gateway aggregate năm downstream call cần câu trả lời rõ cho partial failure: có trả profile thiếu một phần không, có ẩn một widget không, có dùng cached data không, hay fail toàn bộ request? Quyết định đó nên được làm trước, không phải trong incident khi mọi người vẫn đang chờ log hiện ra.

Observability là thứ giữ gateway trung thực. Mỗi incoming request nên có correlation ID hoặc trace ID đi theo nó vào các downstream service. Log nên có route, caller type, tenant hoặc API key khi an toàn, status code, latency, backend được chọn, quyết định rate limit, và lý do timeout. Metric nên cho thấy traffic theo route, error rate, p95 latency, số request bị throttle, upstream failure, và cache hit rate nếu có cache. Trace nên giúp nhìn ra gateway tự nó chậm hay đang đợi backend. Không có visibility đó, gateway sẽ thành nơi ai cũng đổ lỗi nhưng không ai chứng minh được.

Một API gateway tốt thường không gây ấn tượng mạnh. Nó giống một quầy lễ tân vận hành ổn trong một tòa nhà bận rộn: kiểm tra danh tính, chỉ đúng phòng, giữ hàng đợi không làm nhân viên quá tải, và để lại đủ dấu vết để sau này hiểu chuyện gì đã xảy ra. Câu hỏi khỏe hơn không phải là mình có thể đặt cái này vào gateway không? mà là đặt nó ở edge có làm hệ thống rõ hơn, an toàn hơn, và dễ vận hành hơn không? Nếu câu trả lời là không, công việc đó có lẽ nên ở gần service đang sở hữu sự thật hơn. Nếu bạn từng thấy một gateway giúp team đi nhẹ hơn, hoặc từng thấy nó từ từ trở thành nơi mọi shortcut đáp xuống, sự tương phản đó thường là bài học architecture đáng nhớ nhất.

Bạn thấy bài viết thế nào?