ADR Reference: ADR-INT-005
The Backend for Frontend pattern is the mandatory API integration model for all Ascendion mobile applications. Mobile clients have fundamentally different network, battery, and security constraints from web clients. A shared generic API forces over-fetching, incorrect authentication patterns, and performance degradation on every request. This ADR mandates a purpose-built mobile API layer that eliminates these defects by design.
| Field |
Value |
| ADR Reference |
ADR-INT-005 |
| Version |
1.0 |
| Date Raised |
May 2025 |
| Review Date |
November 2025 |
| Author |
Solutions Architecture Practice — Ascendion |
| Status |
ACCEPTED |
| Domain |
Integration Architecture / Mobile Backend |
| ARB Approval |
Required |
| Stakeholders |
Mobile Architects · Backend Engineers · API Designers · Mobile Engineering Leads · Integration Specialists |
Executive Summary
Decision: The Backend for Frontend (BFF) pattern is mandatory for all mobile applications connecting to backend services. Mobile clients must not share an API directly with web clients. GraphQL is the preferred BFF technology for new projects. REST with mobile-optimised conventions is adopted for projects with existing REST infrastructure. gRPC with Protocol Buffers is adopted for high-frequency low-latency data streams. The BFF aggregates microservice calls, applies mobile-appropriate field selection, and enforces mobile-specific authentication flows per ADR-SEC-011.
Decision Drivers
| Priority |
Quality Attribute |
Weight |
Rationale |
| 1 |
Network Efficiency |
25% |
Mobile data is metered. Round trips on cellular cost 50–300ms each. Field over-fetching wastes battery and data. |
| 2 |
Mobile Security |
22% |
Mobile-specific auth (PKCE) must be enforced at the BFF boundary. Web auth patterns are insecure on mobile. |
| 3 |
Offline Capability |
18% |
BFF must support delta sync and offline-first data access patterns. |
| 4 |
Developer Experience |
15% |
Type-safe generated API clients reduce integration errors. Contract testing prevents mobile breakage from backend changes. |
| 5 |
Backend Independence |
12% |
Mobile release cycles are slower than backend. BFF abstracts microservice changes from mobile clients. |
| 6 |
Performance at Scale |
8% |
Caching and aggregation at BFF layer handles 5,000+ concurrent mobile sessions. |
Considered Options
Option A — GraphQL BFF (PREFERRED DEFAULT)
Purpose-built GraphQL layer aggregating multiple microservices. Field selection is native to the protocol — no over-fetching by design. Apollo Kotlin and Apollo iOS generate type-safe client code from the GraphQL schema, eliminating an entire class of serialisation errors. GraphQL subscriptions provide real-time updates without separate WebSocket management. Weighted score: 4.83 / 5.0
Option B — REST BFF with Mobile Conventions (PERMITTED)
Purpose-built REST API for mobile with cursor-based pagination, field selection via ?fields= parameter, batch endpoints, conditional requests with ETag/If-None-Match, and Brotli compression. Adopted when backend team has strong REST expertise and limited GraphQL experience. Weighted score: 4.24 / 5.0
Option C — Shared Generic API (PROHIBITED)
Mobile consuming the same API as web clients. Produces over-fetching, incorrect authentication flows, and performance degradation. Any proposed shared API requires ARB emergency review and documented waiver. Weighted score: 2.09 / 5.0
Option D — gRPC Streaming (SUPPLEMENTARY)
Protocol Buffers binary encoding with bidirectional streaming. 3–10× more compact than JSON. Adopted as a supplement for high-frequency low-latency use cases: real-time location, financial order books, live chat. Not a replacement for the standard BFF pattern.
Decision
GraphQL BFF is the preferred default for all new mobile integrations. REST BFF with mobile conventions is permitted for projects with existing REST infrastructure. Shared API with web is unconditionally prohibited. gRPC supplements the BFF for specific high-frequency streams only.
Repository-to-BFF Mapping: Each Repository method maps to exactly one BFF operation. Aggregation is the BFF's responsibility — the mobile Repository never composes multiple BFF calls.
Offline Sync Contract: All collection endpoints support a since query parameter accepting ISO 8601 timestamp. Deleted records appear as tombstones (id + deletedAt) for a minimum of 30 days.
Push Notification Contract: Payloads must never contain sensitive data — notification_id only. App calls BFF to fetch actual content on notification open.
Trade-off Analysis
| Trade-off Accepted |
Consequence |
Mitigation |
| GraphQL requires DataLoader to prevent N+1 queries |
Without DataLoader, 20-item query triggers 21 database calls |
DataLoader mandatory in all GraphQL BFF implementations. Performance test with 100-item list queries. |
| BFF is an additional service to build and maintain |
Additional infrastructure component, latency hop, operational overhead |
Deploy as serverless function or lightweight container. BFF is typically under 2,000 lines of code. |
| Consumer-driven contract testing requires coordination |
Contract test failures block backend deployments |
Shared Pact Broker. Minimum 2 mobile release cycle deprecation notice period. |
| Delta sync API adds backend complexity |
Backend must maintain tombstones and support since parameter |
Define delta sync requirements in discovery phase. Not all resources require offline sync. |
Implementation Guidance
- Choose GraphQL or REST BFF based on team capability assessment in the first sprint
- Configure Apollo Kotlin or Apollo iOS code generation from the GraphQL schema
- Implement DataLoader pattern for all GraphQL resolvers that access databases
- Set up Pact Broker and write consumer-side contract tests before first API integration
- Configure delta sync endpoint with since parameter for all collection resources
- Set up silent push for background sync — payload contains notification_id only
- Implement cursor-based pagination for all list endpoints (REST) or connection-style (GraphQL)
- Apply Brotli compression on BFF response middleware
Compliance Checkpoints
| Checkpoint |
Trigger |
Owner |
SLA |
| BFF API Architecture Review |
New mobile project — before backend sprint 1 |
Solutions Architect |
Before first API integration |
| Shared API Exception Request |
Any proposal to share API with web clients |
ARB |
Decision within 48 hours |
| Push Payload Security Review |
Any new push notification type |
Security Architect |
Before notification goes to production |
| Pact Contract Broker Active |
Before first backend deployment affecting mobile |
DevOps Lead |
Before first release |
| Delta Sync API Design Review |
Projects with offline-first requirement |
Solutions Architect |
Before data layer implementation |
| Reference |
Title |
Relationship |
| ADR-MOB-001 |
Mobile Application Architecture Pattern |
Repository interface maps directly to BFF endpoints |
| ADR-MOB-002 |
Mobile Platform Selection |
Platform determines API client library (Apollo Kotlin vs Apollo iOS) |
| ADR-MOB-003 |
Mobile CI/CD Pipeline |
Pact consumer tests run in the CI pipeline |
| ADR-SEC-011 |
Mobile Application Security Controls |
OAuth 2.0 PKCE flows implemented at the BFF boundary |
Flowchart
%%{init:{'theme':'base','themeVariables':{'fontSize':'14px','fontFamily':'IBM Plex Sans, system-ui, sans-serif','primaryColor':'#DBEAFE','primaryTextColor':'#1e3a5f','primaryBorderColor':'#2563EB','lineColor':'#374151','clusterBkg':'#F9FAFB','clusterBorder':'#D1D5DB','edgeLabelBackground':'#FFFFFF'},'flowchart':{'curve':'orthogonal','padding':30,'nodeSpacing':65,'rankSpacing':75,'useMaxWidth':true}}}%%
flowchart TD
subgraph MOBILE["📱 Mobile Application"]
direction LR
REPO_BFF["<b>Repository Layer</b><br/>Interface in Domain<br/>Implementation in Data"]
APOLLO["<b>API Client</b><br/>Apollo Kotlin · Apollo iOS<br/>Type-safe generated code"]
LOCAL_BFF["<b>Local Database</b><br/>Room · SwiftData<br/>Single source of truth"]
end
subgraph PROTOCOL["🔀 API Protocol Selection"]
direction LR
GQL["<b>GraphQL — PREFERRED</b><br/>Field selection native<br/>Subscriptions real-time<br/>Score: 4.83/5.0"]
REST_P["<b>REST — PERMITTED</b><br/>Cursor pagination<br/>?fields= selection<br/>Brotli compression"]
GRPC_P["<b>gRPC — SUPPLEMENTARY</b><br/>Protobuf binary<br/>Bidirectional streaming<br/>High-frequency only"]
end
subgraph BFF_LAYER["⚡ Mobile BFF Layer — Mandatory"]
GW_BFF["<b>API Gateway</b><br/>PKCE auth enforcement<br/>Rate limiting · Routing"]
AGG_BFF["<b>Aggregation Layer</b><br/>Composes microservice calls<br/>Field selection · Caching"]
DELTA["<b>Delta Sync</b><br/>?since=timestamp<br/>Tombstones 30 days"]
PUSH_BFF["<b>Push Manager</b><br/>APNs · FCM tokens<br/>Payload: ID only"]
end
subgraph CONTRACT["📋 Contract Testing — Pact"]
direction LR
CONSUMER["<b>Consumer Tests</b><br/>Mobile defines contract<br/>Per Repository method"]
BROKER["<b>Pact Broker</b><br/>Published on every<br/>mobile CI run"]
PROVIDER["<b>Provider Verification</b><br/>Backend CI validates<br/>Blocks deploy on failure"]
end
subgraph BACKEND_BFF["🏗 Backend Microservices"]
direction LR
SVC_U["<b>User Service</b>"]
SVC_T["<b>Transaction Service</b>"]
SVC_P["<b>Product Service</b>"]
SVC_N["<b>Notification Service</b>"]
end
REPO_BFF --> APOLLO --> GW_BFF
LOCAL_BFF <-->|"Delta sync watermark"| DELTA
GW_BFF --> AGG_BFF --> DELTA
AGG_BFF --> GQL & REST_P & GRPC_P
GQL & REST_P & GRPC_P --> SVC_U & SVC_T & SVC_P
PUSH_BFF --> SVC_N
SVC_N -.->|"Silent push · ID only"| MOBILE
CONSUMER --> BROKER --> PROVIDER
PROVIDER -.->|"Gates backend deploy"| BACKEND_BFF
style MOBILE fill:#DBEAFE,stroke:#2563EB,stroke-width:2px
style PROTOCOL fill:#FEF9C3,stroke:#CA8A04,stroke-width:2px
style BFF_LAYER fill:#FEF3C7,stroke:#D97706,stroke-width:2px
style CONTRACT fill:#F3E8FF,stroke:#7C3AED,stroke-width:2px
style BACKEND_BFF fill:#DCFCE7,stroke:#16A34A,stroke-width:2px
style REPO_BFF fill:#BFDBFE,stroke:#2563EB,color:#1e3a5f
style APOLLO fill:#BFDBFE,stroke:#2563EB,color:#1e3a5f
style LOCAL_BFF fill:#BFDBFE,stroke:#2563EB,color:#1e3a5f
style GQL fill:#FEF08A,stroke:#CA8A04,color:#713f12
style REST_P fill:#FDE68A,stroke:#D97706,color:#713f12
style GRPC_P fill:#FCD34D,stroke:#B45309,color:#78350F
style GW_BFF fill:#FDE68A,stroke:#D97706,color:#78350F
style AGG_BFF fill:#FDE68A,stroke:#D97706,color:#78350F
style DELTA fill:#FDE68A,stroke:#D97706,color:#78350F
style PUSH_BFF fill:#FDE68A,stroke:#D97706,color:#78350F
style CONSUMER fill:#E9D5FF,stroke:#7C3AED,color:#4C1D95
style BROKER fill:#E9D5FF,stroke:#7C3AED,color:#4C1D95
style PROVIDER fill:#E9D5FF,stroke:#7C3AED,color:#4C1D95
style SVC_U fill:#BBF7D0,stroke:#16A34A,color:#14532D
style SVC_T fill:#BBF7D0,stroke:#16A34A,color:#14532D
style SVC_P fill:#BBF7D0,stroke:#16A34A,color:#14532D
style SVC_N fill:#BBF7D0,stroke:#16A34A,color:#14532D
References
- Newman, Sam — Backends for Frontends Pattern. samnewman.io/patterns/architectural/bff
- GraphQL Foundation — GraphQL Specification. spec.graphql.org
- Pact Foundation — Consumer-Driven Contract Testing. docs.pact.io
- Apollo — Apollo Kotlin Documentation. apollographql.com/docs/kotlin
- IETF RFC 7807 — Problem Details for HTTP APIs. tools.ietf.org/html/rfc7807
- Google — Firebase Cloud Messaging. firebase.google.com/docs/cloud-messaging
⚠ Shared API with Web Clients — Mobile consuming the same REST or GraphQL API as web clients. Web APIs return full resource representations; the mobile screen renders a fraction. Battery, bandwidth, and parse time wasted on unused fields.
CORRECT: Purpose-built mobile BFF with field selection. Reduces payload 40–70%. Single round trip replaces multiple sequential requests. Mobile-specific authentication enforced at the BFF boundary.
⚠ Offset-Based Pagination for Infinite Scroll — GET /transactions?page=3&limit=20. When a new transaction is inserted before page 3, items shift and the user sees duplicates or skipped records.
CORRECT: Cursor-based pagination. Cursor is opaque and stable regardless of concurrent inserts.
End of Document
Maintained by
Architecture Council
Review Cadence
Annually or upon any
Tier 2 architectural change
Change Requests
Submitted as RFC to the
Architecture Council for review
Version History
Maintained in version
control alongside this document