codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›backend

Wrap public OpenAPIs with your own BFF

Published 2026-05-26·0 views

Wrap public OpenAPIs with your own BFF

Calling a public-sector or third-party OpenAPI directly from the client gets the first screen up quickly. Run it for a few days, though, and the same kinds of incidents repeat — leaked keys, surprising result codes, protocol mismatches. So putting a single BFF layer of your own between the client and the external API is almost always the right call.

1. Four failures direct calls invite

Failure What happens with direct calls What a BFF layer does
Key exposure serviceKey ends up in the client bundle — a public secret Lives in server env vars; client can't see it
Result-code reading HTTP 200 with resultCode=90 empty body → screen quietly shows empty cards BFF normalises 200 + resultCode≠0 to a 5xx
Protocol mismatch "Docs say HTTPS" but only HTTP actually works BFF calls HTTP; client only ever sees HTTPS
Schema drift Vendor flips camelCase ↔ snake_case → client breaks BFF normalises to one shape

2. The most common trap — key propagation lag

After a public API approves your key, propagation through their gateways can take time. The same key can power dataset A immediately while dataset B stays dark for an hour. With direct calls that means "empty card on the launch day of any new dataset." With a BFF:

[Client] ──▶ [BFF /api/x]
                │
                ▼
        Validate resultCode
                │
       ┌────────┴────────┐
       ▼                 ▼
   OK → transform·cache   90 → "Preparing" label

Explicitly showing "preparing" is far more reliable than an empty screen.

3. Five jobs the BFF takes on

  1. Key custody — one place in env. One place to rotate.
  2. Result-code normalisation — vendor's resultCode/status/code → HTTP status or a consistent {ok, data, error}.
  3. Protocol normalisation — HTTP-only · self-hosted · standard-gateway quirks absorbed by the BFF.
  4. Cache policy — same query 10 times a second from the client = one call externally. Cache-Control headers live in the BFF.
  5. Legacy compatibility — when vendor moves v1 → v2, you change the BFF; clients keep working.

4. Before / after

Aspect Direct calls BFF layer
Key location Client bundle (exposed) Server env (isolated)
Day 1 of new dataset Empty card / console error "Preparing" label
Vendor outage Screen down Last cache or explicit message
Vendor schema change Edits scattered One BFF file
Call-rate control Per client One BFF spot

5. Adopting this in your own project

  • Find every place the client directly hits an external domain (fetch('https://external') grep).
  • For each call site, add a one-line /api/x BFF — proxy + normalise + cache header.
  • Collapse the vendor's result codes into a single shape (HTTP status or {ok,error}).
  • Move keys to .env.* and delete them from client code.
  • When onboarding a new dataset, default to the "preparing" branch and flip to normal only after verification.

External APIs are outside your control, but where to absorb their quirks is your choice. The BFF layer is that choice.

More in backend

All in this category →
  • Email Delivery and OTP — SMTP
  • Audit Log — logAdminAction pattern
  • WebSocket and SSE — real-time communication
  • REST API introduction
  • OpenAPI Specification
  • Crawler ethics and tooling