Votre équipe mobile construit une page produit. L'API généraliste renvoie des dizaines de champs que le téléphone n'affiche jamais, et les avis, le stock et la liste d'envies demandent chacun un appel de plus. Chaque modification de ces endpoints attend une équipe API qui sert aussi le site web et trois partenaires.
Un backend for frontend (BFF) donne à chaque expérience client sa propre petite API côté serveur, détenue par l'équipe qui construit le client. Cet article couvre l'origine du pattern, ce qu'un BFF doit faire, sa comparaison avec une API gateway et GraphQL, comment il garde les jetons OAuth hors du navigateur, ses pièges et comment le dessiner.
D'où vient le pattern
SoundCloud a donné son nom au pattern. L'article de Phil Calçado de 2015 décrit des applications bâties sur l'API publique, où une page de profil appelait /tracks/1234.json, /tracks/1234/related.json, /users/86762.json et /users/me.json et fusionnait elle-même les résultats. Quand les équipes client ont possédé leurs backends, elles y ont déplacé la fusion et l'application demandait GET /user-profile/123.json. Le tech lead web, Nick Fisher, a forgé le terme. Calçado résume : « Le BFF faisait partie de l'application. »
L'article Backends For Frontends de Sam Newman, de novembre 2015, l'a généralisé : un backend par expérience utilisateur, maintenu par l'équipe qui construit cette interface.
Clients bavards et API taille unique
- Clients bavards. L'exemple de Newman est une liste d'envies : on récupère la liste, puis les noms, prix et niveaux de stock de ses éléments. Cela fait deux allers-retours dépendants ; à, disons, 150 ms chacun sur un réseau mobile, 300 ms s'écoulent avant le début du rendu. Avec un BFF, le téléphone paie un aller-retour, et les appels dépendants s'exécutent dans le centre de données, où un saut coûte au plus quelques millisecondes.
- Des réponses dimensionnées pour le plus grand écran. Le téléphone télécharge des champs qu'il n'affiche jamais.
- Un goulot d'étranglement partagé. Chaque équipe client met ses changements en file d'attente pour un seul déployable, souvent détenu par une autre équipe.
Les responsabilités d'un BFF
| Responsabilité | Dans le BFF | Pas dans le BFF |
|---|---|---|
| Agrégation | Un endpoint par écran, appelant les services en parallèle | Les jointures dont tout client a besoin ; elles relèvent d'un service |
| Mise en forme des réponses | Choisir, renommer et formater des champs | Les règles métier comme la tarification |
| Authentification et session | Cookie de session, stockage et renouvellement des jetons | L'autorisation finale ; les services décident |
| Cache | Réponses agrégées de courte durée | Des données personnalisées dans un cache indexé seulement par URL |
| Feature flags | Quelle variante ce client voit | Les flags qui changent le comportement du domaine |
BFF vs API gateway vs GraphQL
| API gateway | BFF | Serveur GraphQL | |
|---|---|---|---|
| Sert | Tous les clients | Une expérience client | N'importe quel client, via un schéma unique |
| Détenu en général par | L'équipe plateforme | L'équipe client | Une équipe graph, ou les équipes de domaine via la fédération |
| Fait | TLS, routage, contrôle des jetons, limites de débit | Agrégation, mise en forme, session et jetons | Laisse les clients choisir les champs ; les resolvers appellent les services |
| Change quand un écran change | Non | Oui, dans la même release | Souvent seule la requête change |
| Défaillance typique | La logique métier s'y infiltre | Duplication, fan-out lent | Requêtes coûteuses, appels de resolvers N+1, cache HTTP plus difficile |
Une configuration courante place une gateway en périphérie, avec les BFF derrière, comme dans le schéma d'architecture d'une API gateway. Un graphe partagé peut remplacer les BFF par client, et les recommandations de Microsoft notent qu'avec des resolvers propres à chaque frontend, des BFF séparés peuvent n'apporter rien. Le coût est la frontière d'équipe : chaque équipe client négocie ses changements sur un seul schéma.
Propriété et frontières d'équipe
Le BFF appartient à l'équipe client : l'application web et son BFF changent dans une même pull request et sont livrés dans une même release. Newman note qu'une équipe mobile peut même déplacer de la logique dans son BFF pour livrer sans passer par la validation d'un app store.
Combien de BFF ? Newman cite Stewart Gleadow : une expérience, un BFF. REA Group faisait tourner des BFF distincts pour iOS et Android ; SoundCloud en partageait un entre ses applications d'écoute iOS et Android, et ses ingénieurs ont dit à Newman qu'ils pourraient y repenser. La version de Pete Hodgson consiste à suivre les frontières d'équipe. Votre organigramme d'ingénierie devrait montrer exactement une équipe propriétaire par BFF.
Un BFF partenaire maintient un contrat stable et versionné et le fait correspondre aux services à mesure qu'ils évoluent, de sorte que le travail interne ne casse pas les intégrations des partenaires. Router les partenaires directement vers des API de services versionnées fonctionne aussi.
Le BFF comme gestionnaire de jetons pour les applications de navigateur
Une application monopage qui exécute OAuth elle-même garde les jetons dans le navigateur, où n'importe quel script injecté peut les voler. Le guide JWT recense les endroits où une application de navigateur peut garder ses jetons et le risque de chacun. La RFC 10017, OAuth 2.0 for Browser-Based Applications, est devenue une Best Current Practice (BCP 212) en août 2026. Elle classe trois architectures par ordre décroissant de sécurité :
| Pattern | Où vivent les jetons | Ce que peut faire du JavaScript injecté | Verdict de la RFC 10017 |
|---|---|---|---|
| BFF | Uniquement sur le serveur | Envoyer des requêtes via le BFF tant que la page est ouverte | Fortement recommandé pour les applications métier et sensibles |
| Backend médiateur de jetons | Jeton d'accès dans le navigateur, jeton de rafraîchissement sur le serveur | Voler les jetons d'accès et demander de nouveaux au backend | Seulement quand un BFF complet n'est pas viable |
| Client OAuth dans le navigateur | Tous les jetons dans le navigateur | Voler chaque jeton et lancer de nouveaux flux | Déconseillé pour les applications métier ou sensibles |
Ici, le BFF est un client OAuth confidentiel. Il exécute le flux authorization code avec PKCE, échange le code avec ses propres identifiants, stocke les jetons rattachés à la session de l'utilisateur et joint le jeton d'accès à chaque appel qu'il transmet. Le navigateur ne détient qu'un cookie ; le schéma du flux OAuth 2.0 détaille le flux code.
Les règles principales de la RFC :
- Cookie :
SecureetHttpOnlysont obligatoires ;SameSite=Strict,Path=/, pas deDomainet un préfixe de nom tel que__Host-Http-sont recommandés. Chrome et Firefox appliquent ce préfixe ; Safari, au moment de la rédaction (novembre 2026), n'applique que sa partie__Host-. - CSRF : une défense est obligatoire. Un en-tête personnalisé statique sur chaque appel d'API force un preflight CORS pour les requêtes cross-origin.
- Proxy : ne transmettre qu'aux hôtes de la liste d'autorisation.
- État de session : un magasin côté serveur, que la RFC ne recommande qu'à petite échelle, ou des jetons chiffrés dans le cookie, dans la limite des 4 096 octets par cookie que la RFC 6265 demande aux navigateurs de prendre en charge. Faites durer la session aussi longtemps que le jeton de rafraîchissement.
Set-Cookie: __Host-Http-sid=3f9c...; Secure; HttpOnly; SameSite=Strict; Path=/
// Same-origin fetch sends the cookie by default.
await fetch("/bff/orders", {
method: "POST",
headers: { "Content-Type": "application/json", "X-CSRF": "1" },
body: JSON.stringify(order),
});
Un BFF n'empêche pas le cross-site scripting : du code injecté peut toujours appeler le BFF tant que la page est ouverte, alors conservez une Content Security Policy. Les applications natives suivent plutôt la RFC 8252, en exécutant le flux code avec PKCE dans le navigateur système, si bien qu'un BFF mobile se contente en général de valider un jeton bearer.
Pièges
- Logique dupliquée. Newman préfère un peu de duplication à du code partagé qui couple les BFF. Quand une logique apparaît une troisième fois, extrayez-la : une bibliothèque pour le code technique, un service de domaine pour la logique métier. SoundCloud a construit un UserProfileService après que cinq BFF environ eurent chacun assemblé des profils d'utilisateurs.
- Le BFF comme monolithe. Signes d'alerte : il détient des données de domaine ou des règles métier, d'autres BFF l'appellent, ou plusieurs équipes y committent. Une remise calculée par le BFF web mais pas par le BFF mobile est un bug qu'un client finira par trouver.
- Latence de fan-out. Si un BFF appelle cinq services en parallèle, la probabilité qu'au moins un réponde plus lentement que son propre p99 est de 1 − 0,99^5 ≈ 4,9 % : le p95 du BFF vaut à peu près le p99 des services. The Tail at Scale de Dean et Barroso présente des contre-mesures.
- Un saut de plus. Chaque BFF ajoute de la latence, un déploiement et une rotation d'astreinte, et les services qui limitent le débit par adresse IP ne voient plus que l'adresse du BFF.
Délais d'attente, réponses partielles et circuit breakers
Fixez une échéance par écran et répartissez-la : avec 800 ms dans le BFF, un délai de 300 ms par appel laisse la place à une nouvelle tentative. Exécutez les appels indépendants en parallèle et transmettez l'échéance.
Décidez ensuite quelles données sont indispensables. La liste d'envies de Newman a besoin de la liste, mais peut s'afficher sans les niveaux de stock. Renvoyez ce que vous avez et signalez ce qui manque :
{
"items": [{ "id": "sku-123", "name": "Trail shoe", "price": "$89.00" }],
"stock": null,
"errors": [{ "section": "stock", "reason": "timeout" }]
}
Donnez à chaque service en aval son propre circuit breaker et son propre pool de connexions, pour qu'un service lent échoue vite au lieu de retenir chaque worker ; le pattern circuit breaker traite des seuils et des fallbacks. Ne retentez que les lectures idempotentes, à une seule couche, et ne mettez pas en cache les réponses agrégées plus longtemps que leur partie la plus fraîche ne le permet.
Le schéma d'architecture du BFF
Contenu du diagramme
- Shared services (domain teams)
- Identity provider
- Session store
- Web app
- Web BFF
- Mobile app
- Mobile BFF
- Partner system
- Partner BFF
- Catalog service
- Orders service
- Profile service
- session cookie only
- bearer access token
- client credentials token
- parallel calls + token
- parallel, fewer fields
- stable v1 mapping
- tokens by session ID
- 1. log in (redirect)
- 2. code + PKCE → tokens
Comment le lire :
- Une ligne par expérience client, colorée selon l'équipe propriétaire. Chaque client n'appelle que son propre BFF.
- Chaque BFF se déploie en éventail vers les services partagés ; sa flèche s'arrête au cadre parce qu'il appelle les services dont ses écrans ont besoin.
- Les liens en pointillés ne concernent que la connexion. Le navigateur est redirigé vers le fournisseur d'identité, puis le BFF web échange le code contre des jetons, la même étape que dans une connexion OpenID Connect.
- Les jetons restent côté serveur, dans le magasin de sessions, sous un identifiant de session. Un cookie chiffré fonctionne aussi, et la RFC 10017 le préfère au-delà des petits déploiements.
- Le bloc Markdown liste les réglages du cookie et un exemple de budget par écran.
Dessiner clairement des schémas de BFF
- Donnez une ligne à chaque client, avec son BFF, étiquetée avec l'équipe propriétaire.
- Étiquetez ce qui traverse chaque lien : un cookie de session, un jeton bearer ou des identifiants client.
- Montrez où vivent les jetons, dans un magasin ou dans un cookie chiffré.
- Dessinez la gateway séparément. Une seule boîte pour la gateway et les BFF masque la propriété.
- Surveillez le hub. Une boîte BFF reliée à tous les clients est un backend généraliste.
- Sautez la liste des endpoints. Un lien étiqueté par BFF vers une frontière de services suffit ; un schéma des microservices derrière les BFF couvre le côté services.
Le construire dans Archboard
- Connectez-vous avec Google ou GitHub et créez un diagramme.
- Depuis le pack Modèle C4, ajoutez un Conteneur pour l'application web et pour l'application mobile, et un Système externe pour le partenaire, un par ligne.
- Ajoutez un Conteneur à côté de chaque client pour son BFF, avec une technologie et une description.
- Ajoutez un Cadre du pack Base nommé Shared services (domain teams), contenant trois nœuds Conteneur : catalog, orders et profile.
- Au-dessus de la ligne web, ajoutez un Fournisseur d'identité du pack Sécurité et un nœud Redis du pack Données comme magasin de sessions.
- Reliez chaque client à son BFF et chaque BFF au cadre, étiquetez les liens, mettez en pointillés les deux liens de connexion et colorez chaque ligne par équipe.
- Ajoutez un bloc Markdown de Base avec les réglages du cookie et le budget, et des étiquettes Texte de Base pour les équipes.
Si vos services vivent déjà dans un flowchart Mermaid, le convertisseur Mermaid vous donne un premier brouillon modifiable. L'exemple utilise 13 nœuds de diagramme et reste dans les limites de l'offre Free.
FAQ
Qu'est-ce que le pattern backend for frontend (BFF) ? Une API côté serveur conçue pour une expérience client, comme une application web, une application mobile ou une intégration partenaire, et détenue par l'équipe de ce client. Elle agrège les appels backend et met en forme les réponses.
Quelle est la différence entre un BFF et une API gateway ? Une gateway sert tous les clients et gère le routage, le contrôle des jetons et les limites de débit. Un BFF sert un client et évolue avec ses écrans. Beaucoup de systèmes placent une gateway devant plusieurs BFF.
GraphQL remplace-t-il le pattern BFF ? Il le peut, car les clients choisissent les champs dont ils ont besoin. Quelqu'un doit tout de même posséder le schéma et les limites de requêtes, et un serveur GraphQL conçu pour un seul client est lui-même un BFF.
Comment fonctionne l'authentification d'un BFF ? Le BFF est un client OAuth confidentiel : il exécute le flux authorization code avec PKCE, garde les jetons côté serveur et ne donne au navigateur qu'un cookie de session HttpOnly.
Combien de BFF dois-je avoir ? Un par expérience utilisateur, aligné sur vos équipes. Deux applications avec la même expérience et la même équipe propriétaire peuvent en partager un.