Um Backend for Frontend (BFF) é um serviço de backend dedicado a um frontend específico. Em vez de web, iOS, Android e integrações externas consumirem o mesmo backend genérico, cada cliente recebe uma camada server-side própria para agregar, adaptar e devolver exatamente o payload que aquela interface precisa.
Sam Newman nomeou e popularizou o padrão em 2015, a partir de trabalhos realizados no SoundCloud. Mais de uma década depois, BFF continua sendo uma abordagem útil para equipes que executam microsserviços por trás de múltiplos clientes, e a Microsoft o documenta como um padrão de arquitetura de nuvem.
O problema que um BFF resolve
Um sistema normalmente começa simples:
[ Web app ] ---> [ Backend ] ---> [ Banco / Serviços ]
Depois surgem novos clientes:
- aplicativo mobile;
- integração com parceiros;
- widget;
- painel administrativo;
- clientes internos.
Se todos usam o mesmo backend, esse backend precisa atender necessidades diferentes ao mesmo tempo. Isso gera dois problemas comuns.
Over-fetching e under-fetching
Um endpoint genérico retorna um formato fixo.
Exemplo:
GET /customers/123
Para um painel web, talvez faça sentido retornar:
{
"id": "123",
"name": "Ana",
"email": "ana@example.com",
"orders": [],
"recommendations": [],
"accountSettings": {}
}
Mas um app mobile talvez precise apenas disso:
{
"name": "Ana",
"unreadNotifications": 4
}
Quando o mesmo endpoint atende os dois casos:
- o mobile baixa dados demais e descarta boa parte deles;
- ou precisa fazer várias chamadas extras para montar a tela.
Clientes “tagarelas”
Sem uma API adaptada à tela, o frontend precisa orquestrar tudo:
Mobile Home
├─ GET /profile
├─ GET /notifications/count
├─ GET /feed
└─ GET /recommendations
Isso aumenta:
- latência;
- consumo de bateria;
- complexidade no frontend;
- dificuldade de testar;
- acoplamento entre UI e microsserviços.
O BFF move essa orquestração para o servidor:
Mobile Home
└─ GET /mobile/home
├─ Profile Service
├─ Notification Service
├─ Feed Service
└─ Recommendation Service
O cliente faz uma chamada; o BFF chama os serviços necessários, combina os dados e entrega um payload pronto para a tela.
Como o padrão BFF funciona
O BFF fica entre um cliente específico e os serviços downstream:
[ Web app ] ---> [ Web BFF ] ---\
[ iOS app ] ---> [ iOS BFF ] -----> [ Microservices ]
[ Android app ] ---> [ Android BFF ] ---/
Cada BFF normalmente executa três tarefas.
1. Agregar
O BFF chama vários serviços e retorna uma única resposta para o cliente.
app.get("/mobile/home", async (req, res) => {
const userId = req.user.id;
const [profile, notifications, feed] = await Promise.all([
profileClient.getProfile(userId),
notificationClient.getUnreadCount(userId),
feedClient.getFeed(userId)
]);
res.json({
user: {
name: profile.name,
avatarUrl: profile.avatarUrl
},
unreadNotifications: notifications.count,
feed: feed.items.slice(0, 10)
});
});
Essa é a agregação de API aplicada a uma experiência específica. Para a versão geral do conceito, veja o padrão agregador de API.
2. Remodelar
O BFF adapta o formato para o cliente:
- remove campos desnecessários;
- renomeia propriedades;
- achata objetos aninhados;
- formata valores;
- reduz payloads para mobile;
- retorna respostas mais ricas para desktop.
Exemplo de resposta otimizada para mobile:
{
"name": "Ana",
"avatarUrl": "https://cdn.example.com/avatar.png",
"unreadNotifications": 4,
"latestPosts": [
{
"id": "p1",
"title": "Novo pedido enviado"
}
]
}
3. Traduzir
O BFF também pode lidar com decisões específicas do cliente:
- paginação diferente para mobile e web;
- cache por tipo de cliente;
- tradução entre protocolos;
- composição de dados;
- tratamento de erros adequado à UI.
Os microsserviços continuam genéricos e orientados a capacidades de negócio. O BFF concentra a modelagem específica do cliente.
Se você está revisando sua arquitetura de serviços, estes guias ajudam a contextualizar: microsserviços versus APIs e transição de um monolito para microsserviços.
Um BFF por experiência do cliente
A regra prática é:
uma experiência de cliente distinta = um BFF
Exemplos:
Web app ---> Web BFF
iOS app ---> iOS BFF
Android app ---> Android BFF
Partner API ---> Partner BFF
Isso evita condicionais espalhadas no mesmo backend:
// Sinal de alerta
if (clientType === "mobile") {
return mobilePayload;
}
if (clientType === "web") {
return webPayload;
}
if (clientType === "partner") {
return partnerPayload;
}
Quando um único BFF começa a atender clientes muito diferentes, ele vira novamente um backend genérico.
A exceção: se iOS e Android tiverem experiências quase idênticas e forem mantidos pela mesma equipe, pode fazer sentido usar um único BFF mobile. O critério é similaridade e propriedade, não apenas o nome da plataforma.
A propriedade pertence à equipe de frontend
Um BFF não deve ser apenas “mais uma API” controlada por uma equipe central de backend. A equipe que mantém o cliente deve ser dona do BFF.
Isso permite que a equipe:
- altere UI e endpoint juntos;
- priorize o backlog conforme a necessidade do produto;
- escolha runtime e linguagem adequados;
- publique mudanças sem depender da fila de outra equipe;
- teste o contrato da API junto com a experiência do usuário.
Exemplo de divisão saudável:
Equipe Web
├─ Web App
└─ Web BFF
Equipe Mobile
├─ iOS App
├─ Android App
└─ Mobile BFF
Equipe Plataforma
├─ API Gateway
├─ Observabilidade
└─ Autenticação compartilhada
Essa separação combina bem com a ideia de camada de experiência em conectividade orientada por API.
BFF vs. Gateway de API
BFF e gateway de API parecem parecidos em diagramas, mas resolvem problemas diferentes.
Um gateway de API é um ponto de entrada compartilhado para preocupações transversais:
- autenticação;
- autorização;
- rate limiting;
- roteamento;
- terminação TLS;
- logs;
- métricas;
- políticas globais.
Um BFF é específico de uma experiência:
- agrega dados para uma tela;
- adapta payloads para um cliente;
- traduz necessidades da UI;
- reduz chamadas do frontend;
- isola mudanças por equipe.
Eles podem ser usados juntos:
[ Client ]
|
v
[ API Gateway ]
|
v
[ Client-specific BFF ]
|
v
[ Microservices ]
Use o gateway para o que é igual entre clientes. Use o BFF para o que é diferente.
Para comparações relacionadas, veja:
- Gerenciamento de API vs Gateway de API
- Gateway de API vs Balanceador de Carga
- Service Mesh vs Gateway de API
Quando usar um BFF
Use BFF quando estas condições forem verdadeiras.
Você tem clientes realmente diferentes
Exemplo:
Web dashboard: precisa de dados completos e tabelas grandes
Mobile app: precisa de payloads pequenos e respostas rápidas
Partner API: precisa de formato estável e limitado
Quanto mais as experiências divergem, mais o BFF ajuda.
O backend compartilhado virou gargalo
Sinais comuns:
- toda mudança de frontend exige negociação com várias equipes;
- um endpoint tem muitos parâmetros condicionais;
- o payload cresceu para atender todos os clientes;
- mudanças simples demoram porque afetam consumidores demais.
Você precisa otimizar payload por cliente
Mobile pode priorizar:
- respostas pequenas;
- cache agressivo;
- menos chamadas;
- campos essenciais.
Desktop pode priorizar:
- dados ricos;
- filtros;
- agregações;
- visualizações completas.
A equipe precisa escolher seu próprio runtime
Um BFF pode ser escrito no stack mais produtivo para aquela equipe, desde que respeite os contratos e padrões operacionais da organização.
Quando não usar um BFF
BFF adiciona custo. Evite quando ele não resolve um problema real.
Você tem apenas um cliente
Se existe uma única interface, um BFF provavelmente é só um salto extra.
[ App único ] ---> [ Backend ]
Nesse caso, mantenha a arquitetura simples.
Seus clientes consomem os mesmos dados
Se web e mobile usam praticamente o mesmo payload, BFFs separados podem duplicar esforço sem benefício.
GraphQL já resolve a modelagem
Com GraphQL, cada cliente pode solicitar exatamente os campos necessários a partir de um endpoint. Isso reduz over-fetching e under-fetching.
Se você já tem uma camada GraphQL com resolvers adequados ao frontend, um BFF separado pode não agregar muito. Veja o que é GraphQL antes de adicionar outra camada.
Gateway + microsserviços já são suficientes
Para sistemas simples, um gateway de API na frente de microsserviços bem projetados pode ser o bastante.
Desvantagens reais do BFF
Mesmo quando o padrão se encaixa, ele traz custos.
Duplicação de código
Três BFFs podem acabar implementando a mesma lógica:
- formatação de datas;
- validação comum;
- tratamento de erros;
- headers padrão;
- autenticação auxiliar.
Mitigação:
- mova lógica realmente compartilhada para bibliotecas;
- mantenha autenticação, rate limiting e observabilidade no gateway;
- deixe o BFF focado em adaptação de payload e orquestração por cliente.
Mais serviços para operar
Cada BFF precisa de:
- pipeline de CI/CD;
- deploy;
- monitoramento;
- logs;
- alertas;
- gestão de secrets;
- política de segurança;
- ownership claro.
Se a equipe não consegue operar mais serviços, talvez ainda não seja hora de introduzir BFFs.
Um salto de rede extra
O BFF adiciona uma chamada entre cliente e serviços. Porém, em muitos casos ele reduz a latência percebida porque substitui várias chamadas do cliente por uma única chamada agregada.
Meça:
- p95/p99 de latência;
- tamanho dos payloads;
- número de chamadas por tela;
- taxa de erro;
- tempo de renderização no cliente.
Risco de virar um backend inchado
Um BFF não deve conter regra de negócio central. Essa lógica pertence aos microsserviços.
O BFF deve cuidar principalmente de:
- composição;
- transformação;
- adaptação;
- experiência do cliente.
Se ele começa a possuir regras de negócio amplas, o acoplamento volta.
Implementando um BFF na prática
Um fluxo simples para adotar BFF:
1. Escolha uma tela problemática
Comece pequeno. Por exemplo:
Tela inicial do app mobile
Mapeie as chamadas atuais:
GET /profile
GET /notifications/count
GET /feed
GET /recommendations
2. Defina o payload ideal para o cliente
Não copie os modelos internos dos microsserviços. Modele a resposta pelo que a tela precisa.
{
"user": {
"name": "Ana",
"avatarUrl": "https://cdn.example.com/avatar.png"
},
"unreadNotifications": 4,
"feed": [
{
"id": "post-1",
"title": "Seu pedido foi enviado"
}
]
}
3. Crie um endpoint orientado à experiência
GET /mobile/home
Evite endpoints genéricos demais. O BFF pode expor APIs alinhadas à experiência do cliente.
4. Agregue chamadas em paralelo
Exemplo em Node.js/Express:
app.get("/mobile/home", async (req, res, next) => {
try {
const userId = req.user.id;
const [profile, notificationCount, feed] = await Promise.all([
profileService.getProfile(userId),
notificationService.getUnreadCount(userId),
feedService.getLatest(userId, { limit: 10 })
]);
res.json({
user: {
name: profile.name,
avatarUrl: profile.avatarUrl
},
unreadNotifications: notificationCount,
feed: feed.items.map((item) => ({
id: item.id,
title: item.title
}))
});
} catch (error) {
next(error);
}
});
5. Teste contrato e regressão
Inclua testes para garantir que o BFF entrega o formato esperado:
expect(response.body).toEqual({
user: {
name: expect.any(String),
avatarUrl: expect.any(String)
},
unreadNotifications: expect.any(Number),
feed: expect.any(Array)
});
6. Monitore como produto
Para cada endpoint BFF, monitore:
- latência;
- erros por dependência downstream;
- tamanho da resposta;
- cache hit rate;
- uso por versão do cliente;
- endpoints não utilizados.
Mantendo contratos BFF sincronizados com Apidog
A parte difícil de executar BFFs na prática são os contratos. Cada BFF expõe sua própria API voltada ao cliente e também depende dos contratos dos microsserviços subjacentes. Essa quantidade de interfaces entre equipes pode gerar divergência, bugs e clientes quebrados.
É aqui que o Apidog se encaixa no fluxo de trabalho. Apidog é uma plataforma de design, teste, mocking e documentação de API. Para BFFs, ele ajuda a manter cada contrato em um lugar único.
1. Projete o contrato primeiro
Defina o endpoint do BFF antes de implementar:
GET /mobile/home
Com resposta esperada:
{
"user": {
"name": "string",
"avatarUrl": "string"
},
"unreadNotifications": 0,
"feed": [
{
"id": "string",
"title": "string"
}
]
}
No Apidog, esse contrato pode ser definido visualmente com OpenAPI por baixo. Essa é a abordagem de design de API contrato-primeiro aplicada ao BFF, mantendo o contrato de API explícito.
2. Crie um mock antes da implementação
Com o contrato definido, a equipe de frontend pode começar a desenvolver contra um mock do BFF, sem esperar:
- implementação do BFF;
- disponibilidade dos microsserviços;
- dados reais completos.
Isso reduz bloqueios entre frontend e backend.
3. Teste o contrato no CI
Automatize validações para garantir que o BFF continua retornando o payload esperado.
Exemplos de verificações:
- status code correto;
- campos obrigatórios presentes;
- tipos compatíveis;
- estrutura do JSON estável;
- erros padronizados;
- resposta compatível com o contrato.
Assim, uma mudança downstream que quebre o BFF pode ser detectada antes de chegar ao cliente.
4. Documente para frontend e backend
A documentação interativa gerada a partir do contrato ajuda as equipes a compartilharem a mesma fonte de verdade:
- frontend sabe como consumir o BFF;
- backend entende quais dados o BFF precisa;
- QA sabe quais cenários testar;
- produto consegue visualizar o comportamento esperado.
Escopo importante: o Apidog não constrói, hospeda ou executa seu BFF, e também não é um gateway de API. Ele é usado para projetar, simular, testar e documentar os contratos de API que cada BFF suporta.
Tratar cada BFF como um produto, com contrato estável e bem documentado, torna o padrão mais sustentável.
Checklist para decidir se você precisa de BFF
Use esta lista antes de criar um novo serviço:
[ ] Tenho mais de um cliente?
[ ] Esses clientes precisam de payloads diferentes?
[ ] O frontend faz chamadas demais para montar uma tela?
[ ] O backend compartilhado virou gargalo entre equipes?
[ ] A equipe cliente pode operar o BFF?
[ ] O gateway não resolve esse problema?
[ ] GraphQL não cobre melhor esse caso?
[ ] O contrato do BFF será testado e documentado?
Se a maioria das respostas for “sim”, BFF provavelmente faz sentido.
FAQ
Um BFF é um microsserviço?
Um BFF é um serviço server-side e, em uma arquitetura de microsserviços, geralmente é implantado como um serviço independente. Mas sua função é diferente.
Um microsserviço normalmente possui uma capacidade de negócio. Um BFF possui uma experiência de cliente e existe para agregar e remodelar serviços para esse cliente.
Quantos BFFs devo ter?
A regra prática é um BFF por experiência de cliente distinta.
Exemplo:
Web app -> Web BFF
iOS app -> iOS BFF
Android app -> Android BFF
Combine clientes apenas quando eles forem muito parecidos e tiverem a mesma equipe responsável.
GraphQL substitui BFF?
Pode substituir parte do problema, especialmente a modelagem de payload. GraphQL permite que o cliente peça os campos exatos de que precisa.
BFF ainda pode ser útil quando você precisa de:
- orquestração específica por cliente;
- tradução de protocolo;
- runtime separado;
- lógica de composição fora do servidor GraphQL compartilhado.
Posso usar BFF e gateway de API juntos?
Sim. É comum.
Cliente -> Gateway -> BFF -> Microsserviços
O gateway lida com preocupações compartilhadas. O BFF lida com o que é específico do cliente.
Quem deve ser dono do BFF?
A equipe que mantém o frontend correspondente. Essa propriedade é central para o padrão, porque permite entregar mudanças de UI e API juntas.
Um BFF adiciona latência?
Ele adiciona um salto de rede, então existe custo. Porém, muitas vezes reduz a latência total percebida porque diminui o número de chamadas feitas pelo cliente e permite que o BFF chame serviços em paralelo.
Meça antes e depois.

Top comments (0)