ArquiteturaIntermediário7 min de leitura5 seções2015, Data aproximada

Backend for Frontend (BFF)

Uma API genérica que tenta servir web, iOS e Android ao mesmo tempo acaba servindo mal a todos. O BFF é um backend por tipo de cliente, moldado às necessidades daquela interface: ele agrega chamadas, enxuga campos e formata a resposta sob medida. Cada frontend ganha um backend que fala a língua dele — ao preço de mais um serviço por cliente para manter, e do risco de duplicar lógica entre eles.

Em 10 segundos

O BFF é um backend por tipo de cliente (web, iOS, Android), cuja função é servir aquela interface sob medida: agrega chamadas, enxuga campos, formata a resposta. Resolve o problema da API genérica que serve mal a todos porque tenta servir a todos. O custo é mais um serviço por cliente para manter, e o risco de duplicar entre os BFFs a lógica que era comum — que, se é de domínio, deveria ficar nos serviços, não na borda.

Antes de ter nome

É uma especialização do API Gateway: em vez de um portão para todos, um backend por tipo de cliente, moldado às necessidades daquela interface.

  • #arquitetura
  • #api
  • #frontend
  • #agregacao
  • #cliente
Analogia

O garçom que conhece a mesa

Numa cozinha que atende salão, delivery e balcão, mandar o mesmo prato empratado do mesmo jeito para os três serve mal todo mundo: o delivery precisa embalado, o balcão precisa rápido, o salão precisa bonito. O BFF é o garçom especializado de cada canal: a cozinha (os serviços de domínio) prepara os ingredientes, e cada garçom monta e entrega do jeito que a sua mesa precisa. Um garçom por canal custa mais gente — mas cada mesa recebe exatamente o que espera, sem a cozinha ter que adivinhar para quem está cozinhando.

01Conceito

Um backend que fala a língua do cliente

O BFF não é uma camada a mais por capricho: ele existe porque a fronteira entre o backend genérico e a tela específica é onde mais aparece atrito. A resposta ideal para a home do app não é a ideal para a home do desktop, e forçar as duas numa API só empobrece ambas.

A responsabilidade do BFF é estreita e clara: agregar (juntar várias chamadas numa só), adaptar (mandar só os campos que a tela usa) e formatar (a estrutura que aquele cliente consome). Ele é fino — a regra de negócio continua nos serviços.

O BFF é uma especialização do API Gateway, e a diferença importa. O gateway é um portão único para todos os clientes, focado em tarefas transversais (auth, rate limit, roteamento); o BFF é um portão por cliente, focado em moldar a resposta àquela interface. Muitos sistemas têm os dois: o gateway na frente cuida do transversal, e atrás dele há um BFF por tipo de cliente cuidando da adaptação. Confundi-los leva a um gateway inchado tentando também formatar respostas — ou a BFFs reimplementando auth que já era do gateway.

A ligação com a Lei de Conway é direta e explica por que o padrão nasceu: um BFF costuma existir porque há um time dono daquele frontend, que quer evoluir seu backend sem depender do time de plataforma. A arquitetura (um backend por cliente) espelha a organização (um time por cliente). O risco a vigiar é a duplicação: se a mesma regra aparece no BFF de web e no de mobile, ou ela é de apresentação (tudo bem, cada tela é diferente) ou é de domínio — e aí ela vazou para a borda e deveria voltar para os serviços, antes que as cópias divirjam.

02No mundo real

Como isso aparece na prática

A home mobile que fazia cinco chamadas

Cenário

Para montar a tela inicial, o app fazia cinco requisições a uma API genérica e descartava metade dos campos que vinham. Em redes móveis lentas, a home demorava e consumia bateria e dados à toa.

Como o padrão entra

Um BFF mobile passou a agregar as cinco chamadas numa só e a devolver exatamente os campos daquela tela. O app passou a fazer uma requisição enxuta por tela.

Trade-off: Surgiu um serviço BFF a mais para o time mobile manter e versionar. Em troca, a home ficou rápida, e o app deixou de carregar dados que nunca usava.

A regra de negócio que vazou para os BFFs

Cenário

O cálculo de elegibilidade de um desconto foi implementado no BFF de web e, depois, copiado no BFF de mobile. As duas cópias divergiram, e web e app passaram a mostrar descontos diferentes para o mesmo usuário.

Como o padrão entra

O cálculo foi movido para o serviço de domínio, e os BFFs voltaram a só agregar e formatar. A regra passou a existir num lugar só, consumida por ambos.

Trade-off: Os BFFs ficaram mais 'burros', dependendo de mais um serviço. É exatamente o objetivo: regra de negócio mora no domínio; o BFF só adapta para o cliente.

03Cuidado

Onde isto dá errado

  1. Colocar regra de negócio no BFF

    O BFF deve agregar e formatar, não decidir. Regra de negócio na borda tende a ser copiada para cada BFF e a divergir entre eles — web e mobile passam a discordar sobre o mesmo fato. Regra mora no domínio.

  2. Criar um BFF sem clientes distintos

    Se há um tipo de cliente só, ou todos precisam do mesmo, o BFF é uma camada de rede a mais sem função. O padrão se paga quando as necessidades por cliente são genuinamente diferentes.

  3. Confundir BFF com API Gateway

    O gateway é um portão único focado no transversal (auth, rate limit); o BFF é por cliente e focado em moldar a resposta. Fundir os dois gera um gateway inchado formatando respostas — responsabilidades que deveriam ficar separadas.

04Implementação

Agregar e enxugar por cliente

// Sem BFF: uma API generica serve web, iOS e Android. O app mobile
// faz 5 chamadas e recebe campos que nao usa — rede lenta, bateria.
await Promise.all([
  fetch("/api/usuario"), fetch("/api/pedidos"),
  fetch("/api/enderecos"), fetch("/api/pontos"), fetch("/api/cupons"),
]); // 5 idas ao servidor so para montar UMA tela do celular.

// COM BFF: um backend por tipo de cliente, moldado a ELE.
// bff-mobile agrega e enxuga para a tela do app numa chamada so:
app.get("/mobile/home", async (req, res) => {
  const [usuario, pedidos, pontos] = await Promise.all([
    servicos.usuario(req.userId),
    servicos.pedidos(req.userId),
    servicos.fidelidade(req.userId),
  ]);
  res.json({                       // resposta sob medida para a home mobile:
    nome: usuario.nome,            // so os campos que ESTA tela usa
    ultimosPedidos: pedidos.slice(0, 3),
    pontos: pontos.total,
  });
});
// O app faz 1 chamada e recebe exatamente o que a tela precisa.
// O bff-web pode devolver algo diferente para a MESMA home no desktop.
05Decisão

Quando usar × quando evitar

Use quando

3
  • Quando clientes diferentes têm necessidades de dados e formato distintas.
  • Para poupar rede e bateria do mobile agregando chamadas.
  • Quando cada frontend tem um time que quer evoluir no próprio ritmo.

Evite quando

2
  • Quando há um único tipo de cliente ou necessidades quase iguais.
  • Quando a lógica seria de domínio e deveria viver nos serviços.

Testar o que ficou

3 armadilhas de Backend for Frontend (BFF) viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.

Onde isto aparece de verdade

Você já usa isto, talvez sem saber o nome.

  • um backend por app (web, iOS, Android)Cada cliente ganha um backend feito sob medida para as necessidades dele, em vez de uma API genérica para todos.
  • o BFF do SoundCloud / NetflixAs empresas que popularizaram o padrão, cansadas de uma API única tentando servir web e mobile ao mesmo tempo.
  • agregar chamadas para o mobileUm BFF junta várias chamadas de serviços numa resposta só, poupando a rede lenta e a bateria do celular.

O padrão em uma linha

Sem nome de domínio, sem cerimônia. Só a ideia.

// API moldada para UMA experiência de UI.
const home = await bff.montarHome(userId); // agrega 3 serviços

O que ele cobra

2 saltos a mais entre a chamada e o efeito.

  • Mais um serviço por tipo de cliente para desenvolver, versionar e manter em pé
  • Lógica pode se duplicar entre os BFFs se algo comum a todos os clientes for parar em cada um

Não vale se: há um único tipo de cliente, ou os clientes têm necessidades quase idênticas — aí um backend só serve a todos sem atrito.

Costuma ser confundido com

Onde isto aparece

Continue por aqui