BackendLesson 1 of 49 min

It is a trust boundary, not a screen

The real reason a backend exists: some things must not be decided on a machine the user controls.

The frontend runs on a computer belonging to your user. They can open it, read it, change it, and lie to it. This is not a hypothetical: the developer tools shipped in every browser are enough to rewrite what your frontend does before it talks to you.

Once you hold that idea, a lot of confusing advice snaps into shape. Why can you not just check "is this user an admin" in the browser? Because the browser belongs to them. Why can you not put your API key in the frontend? Because they can read it. Why does the server validate the form again after the frontend already did? Because the frontend check was a courtesy, not a control.

Frontend is right for

  • Making things feel fast and pleasant
  • Catching typos before a round trip
  • Anything that only affects this one person’s screen

Backend is required for

  • Deciding who is allowed to do what
  • Anything involving money, or other people’s data
  • Anything a user could profit from lying about

You will hear "never trust the client". This is what it means. Not that users are malicious, since most are not, but that the frontend is a place where correctness cannot be enforced, only encouraged.

What to remember

  • The frontend runs on a machine the user controls and can modify.
  • Frontend validation is UX. Backend validation is security. You need both.
  • Hiding a control is not the same as preventing the action behind it.

Terms in this lesson

Field notes

Loaded from a deliberately slow source. The lesson above was already readable while this was still travelling. That is streaming, and it is the same trick a chat interface uses.

The URL that read everyone’s invoices

An invoice page checked that you were logged in and then loaded whatever id was in the address. Changing the number showed somebody else’s invoice. It was found by a customer who mistyped, not by a review.

Classic IDOR, still extremely common

The key in the client bundle

An API key was placed behind the public environment prefix so it would be readable from the frontend. It worked. It was also visible to every visitor, and was being used by strangers within a week.

Scraped from a public bundle

resolved in 899ms · region iad1

Hide field notes toggles a search param the loader reads. With it off, the slow promise is never created, so nothing streams.