Why We Built a BFF Layer for Our Admin Platform
How a dedicated Backend-for-Frontend service reduced API calls from 12 to 2 per page, simplified error handling, and gave frontend teams autonomy over their data contracts.
Every frontend team eventually hits the N+1 API problem. Our admin portal needed data from different services — user info, transactions, analytics, notifications — and each required separate API calls. The frontend was orchestrating 8-12 calls per page load, in waterfall sequence, each dependent on the previous. Error handling was a nightmare. Page load times averaged 4-6 seconds.
The BFF Solution
We built a dedicated Backend-for-Frontend (BFF) service per frontend (Merchant Portal, Admin Dashboard), each with optimized endpoints, per-endpoint caching, and fault isolation.
Key design decisions:
- Parallel aggregation using Java CompletableFuture — downstream calls happen concurrently, not sequentially
- Type-safe contracts via OpenAPI with auto-generated TypeScript types — frontend and backend share a single source of truth
- Per-endpoint circuit breakers using Resilience4j — non-critical features degrade gracefully without affecting critical paths
- Redis caching with TTL-based invalidation — high-traffic endpoints hit cache, not databases
- Feature flags per BFF route — frontend features ship independently of backend deployments
Impact
API calls per page dropped from 12 to 2-3. Page load time improved by 35%. Frontend code complexity reduced by roughly 30% — all orchestration logic moved to the BFF where it belongs. The unexpected win: frontend team velocity improved because they were no longer blocked by API integration work.
A BFF isn't just an architectural pattern — it's a team autonomy boundary. Your frontend team should own their BFF.