Where does the auth check happen? Two architectural patterns, with very different blast radii when something goes wrong.
| Pattern | Where checks live | Pro | Con |
|---|---|---|---|
| Perimeter | Network/proxy layer (VPN, firewall, reverse proxy) | Apps don't need to know about auth at all | One layer = one mistake away from total exposure |
| Per-request | Inside each app (middleware, route decorator) | Defense in depth; bypassing one route doesn't bypass others | Repeated logic, easy to forget on a new endpoint |
Solo dev reality: both, layered
This is the entire reason for the "two cheap locks" model:
- Tailscale = perimeter — only devices in your tailnet can even reach the host. (Track 4)
- PIN middleware = per-request — even devices in the tailnet need a session cookie to hit any non-public endpoint. (Track 5)
Where to put per-request auth
In FastAPI, Express, Flask, or any modern web framework: middleware, not per-route checks. Middleware runs before every request hits a handler, so you can't forget to add it on a new route.