Least privilege is the principle everyone agrees with and almost nobody implements well. The reason isn’t ignorance — it’s friction. When the secure path is slow and the insecure path is fast, people route around the controls. Someone gets a broad grant “just to unblock the deploy,” and three years later it is still there.
Good least-privilege design isn’t about saying no. It’s about making the right amount of access easy to get, easy to scope, and easy to take away.
Why static roles rot
The classic failure is permanent role assignment. An engineer joins the on-call rotation and gets production access. They rotate off — but the grant stays. Multiply that across years of joiners, movers and leavers and you get privilege creep: a fleet where everyone can reach everything and nobody can explain why.
Access that never expires is access nobody remembers granting.
A model that holds up
We think about access as three questions kept separate: who is acting, what they may do, and where it needs a second look.
- A separate identity for every actor. People sign in as themselves. Workflows and AI clients act through an agent access of their own, which can never exceed the person who created it.
- Scope the action. Connecting is different from changing things. Reading a database is
database.query_readand writing it isdatabase.query_write; watching a live session and taking it over are separate permissions too. - Gate the targets that matter. Put sensitive servers, internal apps and clusters behind “require approval to connect”, so a role that can open terminals still needs a grant for
db-primary. - Make grants temporary by default. Just-in-time grants expire on their own, and agent accesses and storage keys carry an expiry too.
Just-in-time over standing access
The highest-leverage change is to flip from standing access to just-in-time grants. Instead of holding production privileges permanently, an engineer requests access when they need it, for as long as they need it. When the window closes, the grant is gone — no cleanup ticket, no quarterly backlog. (In Subnomic, just-in-time access and break-glass come with the Enterprise tier.)
It sounds like more friction; in practice it is less. The request is a click, the approval names the target and the reason, and nobody has to remember to revoke anything.
Break-glass, deliberately
Emergencies happen. A good model includes an explicit break-glass path: access granted instantly, but loudly. Break-glass in Subnomic needs a written justification, lasts fifteen minutes by default, writes a critical log entry and notifies every owner and admin at once.
Make the audit trivial
When access is personal, scoped and time-boxed, the access review stops being archaeology. “Who can reach prod-db right now?” has a precise answer, and an access review freezes a snapshot of every member’s effective access for the auditor. Pair that with session recording and you can answer not just who could, but who did — and exactly what they ran.
The payoff
Least privilege that people actually use is the version where the secure path is also the convenient one. Personal identities, action-level permissions, gated targets and automatic expiry shrink the attack surface without slowing anyone down.
See how this works in Fleet.