A BFF in front of every frontend
Why our public blog and our dashboard never talk to the API directly — and what the extra hop buys us in security, caching and simplicity.
Amina Odhiambo
Staff Engineer
1 min read
Both of our frontends are SvelteKit apps, and both have a server layer. We treat that layer as a backend for frontend: the browser talks only to its own origin, and the BFF forwards authenticated API calls server-to-server.
What the browser never sees
The access JWT is short-lived and held in memory; the rotating refresh token stays in an httpOnly cookie. A server-side BFF can keep the access JWT on the server too.
const result = await fetch(`${BACKEND_URL}/v1/admin/articles`, {
headers: { authorization: `Bearer ${accessToken}` }
});Parse twice, trust once
Every request is validated by the same Zod contract at the BFF and again at the API. The duplicate parse is cheap; the guarantee that nothing unvalidated reaches the domain is not.
Errors stay boring
The API returns one of ten fixed error codes. The BFF maps them to a form failure, a redirect or an error page — never a stack trace.
One contract package, shared by both sides
One error vocabulary
One place that knows the API address
The best boundary is the one you can draw on a whiteboard in one line.