Skip to main content

API Gateway & BFF patterns

· 10 min read
Andrey Ganyushkin

API Gateway pattern

Then our application consists of a set of microservices it would be a wrong decision to implement interactions between clients and services directly as drawn on diagram below

monolithic without API Gateway

it is not so good idea to share all microservices with world. Clients should knows about microservices. Also, in this approach we should implement user authentication method for all services, we can't have platform authentication in hidden platform layer. All clients should support changes occurring from services and it can cause an additional work to update clients (mobile for example, not so easy to update).

The main problem:

How do the clients of a Microservices-based application access the individual services? taken from here

application with API Gateway

API Gateway is it a service between UI and backend (or set of backend services) which provides ability for UI to work with the system in some kind of abstraction layer under backend services.

API Gateway provide a lot of benefits for the system, for operations, for monitoring and keeping the system in green status.

API Gateway works as a reverse proxy between clients and the backend microservices architecture.

Benefits and problems

Good points related to API Gateway:

  • Reduced complexity for clients
  • Different protocols for backends and frontends
  • Authentication and Authorization for users and backend services
  • Transforming the requests and responses
  • Aggregating the data from different backend services
  • Caching
  • Performance improvements with caching and data preprocessing
  • Rate limiting
  • Error handling
  • Logging and tracing
  • Monitoring
  • Throttling the API requests

Problems with the API Gateway:

  • single point of failure
  • increased latency
  • API Gateway complexity for big applications
  • cost and time consumption to organize and support API Gateway

Which problems API Gateway can solve?

In additional to the list above, here is some of the problems with details which can be solved by API Gateway pattern:

  • Transforming the responses. API Gateway can transform responses and keep only those data that is required for client. transform payload

  • Performance optimization for slow clients. Filtering, sorting or other expensive operations can be delegated to API Gateway service.

  • Interact with backend services, hide authentication mechanis and tokens for it. Also, with API Gateway it is easy to implement and decouple different authentication methods for clients and backend services.

API Gateway can provide different authentication for fronend and backend

  • Cross-Origin Resource Sharing (CORS). Not all services allows this. And not all existing services was desined to work with browser. Sometimes it is can take a lot of time or impossible to connect from browser to services directly.

  • Preventing system overload by using a speed limit the API Gateway can keep the services in working condition.

API Gateway it is not a Load Balancer

The main defferent between API Gateway and Load Balancer:

Load Balancer - it is component to distribute requests in set of servers with one service

API Gateway - it is component to route requests to different services by different conditions

API Gateway and Load Balancer

Backend-for-Frontend (BFF) pattern

BFF defines a separate API gateway for each kind of client and tightly coupled to a specific user experience.

The BFF pattern is an architectural paradigm, a variant of the API gateway pattern and it comprises of multiple back-ends that are designed to meet the demands of specific front-end applications, such as desktop, browser, and native-mobile applications, IOT devices etc. quote source

Sometimes BFF pattern is called as "specific case of API Gateway" or "separate API Gateway for each client type". In other words, if we have only one client type (web for example) we will use API Gateway, but if we have different types of clients (different protocols, etc...) we will use BFF (separate API Gateway) for each client type.

BFF pattern it is simple dedicated backend for each client type (web, desktop, mobile, ...). Each client will send requests only to its own backend.

Backend-for-Frontend

Here we have special backend for each interface (web, mobile, desktop, tool, etc...). In the BFF component we can optimize API, performance or other aspects of interaction with the client.

BFF pattern is useful when you want to avoid customizing a single backend for multiple interfaces. If we have requirement to optimize or change protocol with a specific client we can keep other clients as is.

BFF component for web can host UI as static assets and browsers will load SPA UI from BFF server and send requests to this server.

Which problems BFF can solve?

  • Different client types, different protocols and API logic.
  • Different types of authentication.
  • "single point of failure" will be splitted by different BFF backends.
  • Conflicting update requirements for different clients.
  • API Gateway will be bottleneck for client teams and can increase time to market for new features.

The main difference between API Gateway and BFF

BFF pattern it is way to organize API for different types of clients. This is a easyest way because BFF eliminates all the differences in individual backends.

![Backend-for-Frontend](bff-APIGW vs BFF.png)

Tools and frameworks

Java Spring

In Spring word we have very interesting Spring conponent Spring Cloud Gateway to implement both API Gateway and BFF patters.

From documentation

This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 5, Spring Boot 2 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

It is very powerful and flexible tool which will cover all your needs.

Can be implemented in code as well as in configuration:

in code

@Configuration
class PlantAPIGatewayConfig {
@Bean
RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("plant-props-routing ", route ->
route.path("/api/v1/plant/**")
.and()
.method(HttpMethod.GET)
.filters(filter -> filter.stripPrefix(1))
.uri("https://plant-storage.dom"))
.build();
}
}
// Transformation in this example drops prefix from url path. "/api" for this example.

or completly in configuration

-- application.yml
spring:
cloud:
gateway:
routes:
- id: read_only_processor_route
uri: https://plant-storage.dom
predicates:
- Method=GET
- Path=/api/v1/plant/property/{propId},/api/v1/plant/image/{imId}

Benefits:

Most of the Spring features are available to use with Spring Cloud Gateway:

Disadvantages:

  • Need to have dedicated service for this implementation. Need to manage this as a component in your system.
  • UI team which works with JavaScript or TypeString cant support this in BFF pattern.
  • Aggregating is not supported. gihub: Have Routes Support Multiple URIs. But can be implemented with Spring MVC in the same service.

Angular and NestJS

This approach can be used with both API Gateway and BFF. But, better for BFF pattern, because for API Gateway it is less flexible then Spring Cloud Gateway. In case BFF, it is great choose, because all code are in one style, in one technology stack. Or if you have only one client type (browser) and you want to delegate API Gateway component to UI team you can use NestJS too.

In NestJS, code such as the domain model or some services can be shared between Angular UI and NestJS backend.

For backend developers NestJS won't be something completely new. Spring Boot and NestJS

http-proxy-middleware can be used with NestJS to organize proxy module in gateway. This middleware provides ability to transform requests and responses, implement authentication and error handling.

NestJS framework seems very similar to Angular code and it provide same expirience for UI developers to write code for Angular UI and NestJS backend.

NestJS example. It is really seems like Angular code.

// domain
export interface IPlant {
name: string;
}

// controller
import { Controller, Get } from '@nestjs/common';
import { IPlant } from './interfaces/plant.interface';

@Controller('plants')
export class PlantController {
constructor(private plantService: PlantService) {}

@Get()
findAll(): IPant[] {
return this.plantService.findAll();
}
}

// service
import { Injectable } from '@nestjs/common';
import { IPlant } from './interfaces/plant.interface';

@Injectable()
export class PlantService {
findAll(): IPant[] {
return [
{ name: "Betula pendula" }
];
}
}

GraphQL

I'm not a big expert on GraphQL, here I just want to summorize some common knowledge about this apporach.

  • GraphQL can be used for API Gateway or BFF implementation.
  • Different protocols to interact with services can be implemented with GraphQL.
  • GraphQL service can be implemented in NodeJS. For example with with NestJS.
  • GraphQL service can be implemented in Spring. It means we can have all benefits from Spring platform.

API Gateway pattern can be inplemented with GraphQL + Spring and supports by one of the backend teams. For BFF, GraphQL can be implemented in NodeJS with NestJS or with other framework.

Cloud providers (serverless)

Each cloud has API Gateway service.

Other services and tools

Monorepo for BFF and maybe for API Gateway

In case of API Gateway and BFF, monorepo allows us to avoid code duplication between frontend and backend. All API components are developed as shared components in monorepo and each BFF service can include required API components.

Interesting technology stack examples to organize code charing approaches below.

UI based technology stack

  • Nx - monorepo management tool
  • TypeScript - shared assets
  • Angular - framework for web
  • NestJS - to implement API Gateway or BFF

backend based technology stack

.NET can cover them all

Interesting solution can be implemented based on .NET

  • monorepo can be implemented in 'solution' in VS. Inside solution we have all dev tools and all code in one please.
  • C# - shared assets. Can be used for backend and frontend development.
  • ASP.NET Core - framework for services. open-source. Supports: Windows, Linux, macOS.
  • Blazor - root technology for ui which can be shared between frontend, backend, mobile, desktop, ...
  • Blazor WASM - SPA framework which uses C# and Blazor shared components

In this technology stack we have one language (C#) and shared code between

  • different services
  • different UI applications
  • UI applciations and backend services
  • UI components between different UI clients (Web, Desktop, Mobile)
  • RestClient can be shared between services and UI

Docs:

Full Stack C# with Blazor

Pattern: API Gateway / Backends for Frontends (microservices.io)

The API gateway pattern versus the Direct client-to-microservice communication (.NET architecture)

API gateway pattern (AWS)

Choosing the Right API Gateway Pattern for Effective API Delivery (nginx.com)