- ~60%
- Lower p95 on aggregated screens
- 8 → 1
- Client round trips per screen
- ~50%
- Smaller response payloads
Overview
The aggregation layer that sits between SwiffyLabs client applications and the core backend. It started as an intern prototype to decouple frontend clients from the microservices behind them, and became the layer every surface goes through. Policy engines and merchant portals get orchestrated behind it; the client receives exactly the data the screen needs and nothing else.
The shape of it
Rendering a loan-offer screen — same data, two architectures.
- 1
- Client round trips
- 175 units
- Critical path
- Server
- Data shaping
What it took
- 01
Architected and owned the end-to-end BFF layer over gRPC and HTTP microservices, optimising payload structures and cutting response latency.
- 02
Designed the initial service prototypes that decoupled frontend clients from core backend microservices — the work that justified the layer existing.
- 03
Implemented Keycloak authentication with SSO and MFA across the layer, so every client inherits one auth story.
- 04
Defined Swagger API contracts up front, which turned integration from a conversation into a generated client.
- 05
Eliminated client-side over-fetching — the frontend became purely presentational, with no data transformation left in it.
Code
1// One resolver per screen. The client asks for a screen, not for entities.2export async function resolveLoanOfferScreen(ctx: RequestContext) {3 // Fan out over gRPC in parallel — the critical path is the slowest call,4 // not the sum of all of them.5 const [customer, eligibility, offers, merchant, policy] = await Promise.all([6 customerClient.get({ id: ctx.customerId }),7 eligibilityClient.evaluate({ customerId: ctx.customerId }),8 offersClient.list({ customerId: ctx.customerId }),9 merchantClient.get({ id: ctx.merchantId }),10 policyClient.resolve({ product: 'CONSUMER_DURABLES' }),11 ].map(settle));12 13 // Partial failure is a first-class outcome: a degraded card, not a blank page.14 return {15 header: pick(customer, ['displayName', 'maskedMobile']),16 offers: offers.ok ? offers.value.map(toOfferCard) : degraded('offers'),17 eligibility: eligibility.ok ? toBanner(eligibility.value) : degraded('eligibility'),18 merchant: merchant.ok ? toMerchantChip(merchant.value) : null,19 disclosures: policy.ok ? policy.value.disclosures : [],20 traceId: ctx.traceId, // every response carries it — support tickets become waterfalls21 };22}