← all case studiesRide-hailing super-app · Southeast Asia · 2020 · team lead

[ CASE STUDY — 02 ]

One call instead of six: a BFF for a super-app home screen

Calls per screen open
6 → 1
Daily volume
100M+
Latency
<50ms p90
Migration
~1 mo to 90%

[ 01Context ]

A ride-hailing super-app in Southeast Asia. The transport home screen — the app's front door — assembled itself from five-plus APIs: trip history, location, balance, marketing banners, nearby drivers, and more. I was the lead engineer on the team that owned the screen.

[ 02Problem ]

Two problems, one forcing the other:

  • The screen fired five-plus API calls on every open — multiplied latency, multiplied failure modes, and client-side orchestration code to maintain
  • A regulatory requirement made phone-number anonymization mandatory on a deadline — the fastest compliant path added yet another call to the pile

[ 03The architecture shift ]

Before: the mobile app's home screen called five-plus APIs itself — history, location, balance, marketing banner, and nearby drivers — with a sixth call for contact masking added later on a regulatory deadline. Five-plus calls per screen open, waterfall latency, orchestration living in the client.

After: the home screen makes one call to a Go BFF on Kubernetes, which fans out in parallel to the six downstream services with per-service timeouts and per-service caching — contact, balance, history cached, driver locations cached 15 seconds — serving 100 million-plus calls per day at under 50 milliseconds p90.

Representative schematic — details anonymized, architecture faithful

[ 04What I did ]

  1. Phase 0

    The deadline fix — deliberate tech debt

    • Shipped contact masking the fastest compliant way: one more API call on the pile
    • Took the debt knowingly, with an explicit plan to return and fix the architecture — the masking feature was later adopted org-wide
  2. Phase 1

    The BFF

    • One Go service on Kubernetes: a single request returns everything the screen needs
    • Parallel fan-out with per-service timeouts — critical failures fail the call and the client retries; optional data (banners) degrades gracefully
    • Per-downstream SLA contracts with per-service cache config — contact info, balance, history cached; driver locations cached 15 seconds
    • Per-API paging thresholds: critical APIs page both teams, non-critical page downstream only until the threshold
  3. Phase 2

    The rollout

    • Dual-served both API shapes so old app versions kept working — ~1 month to 90% of users migrated, forced update at 3 months per app policy
    • Worked with downstream teams to optimize their APIs so the aggregate could hold the 50ms budget

[ 05Result ]

  • 100M+ calls/day at <50ms p90
  • One call instead of five-plus — reliability and client-code simplicity in the same move
  • Zero incidents through rollout
  • Product cycles got faster: new home-screen data became one BFF change instead of N client integrations
  • The regulatory-deadline tech debt was paid down as soon as the anonymization project shipped

Why it matters for productionizing agents

Same playbook as any fan-out system — including agent pipelines calling many tools and models: parallel calls with per-call timeouts, explicit critical-vs-optional failure modes, latency budgets held by contract and caching. Reliability isn't a feature you bolt on after the demo — it's the architecture.

Need this kind of reliability?