Just-in-Time Data Access
also called Time-Boxed Data Grant, Expiring Analytical Access
Replacing permanent read grants with short-lived grants issued on request with a recorded purpose, so that entitlement decays by default instead of accumulating for as long as someone stays employed.
An analyst joins a group on a Tuesday to answer one question about churn. Four years later she has moved teams twice, still holds that group, and the group has since been granted read on 300 more tables. Nobody did anything wrong. Standing grants accumulate because the cost of granting is borne once and the cost of holding is borne by nobody, so the only force acting on an access list is growth.
Just-in-time access inverts the default. A grant is issued when it is asked for, carries a recorded purpose, and expires on its own. Removing access stops being a project somebody has to champion and becomes the thing that happens when nothing happens.
The distinguishing axis is duration, not purpose. Purpose-based access asks why; just-in-time asks for how long. They compose well and they solve different failures: purpose answers the regulator's question about lawful use, expiry answers the auditor's question about who can see the table today.
Why it matters
The blast radius of any credential compromise, insider incident or misconfigured export is the union of what its holder can read, and standing grants make that union close to everything the holder has ever needed. In estates four or more years old, 60% to 80% of granted principal-table pairs are never exercised in a 90-day window, which is a direct measure of how much of the blast radius is buying nothing.
It also makes access reviews tractable. A quarterly review of 900 analysts against 300 groups is a rubber stamp because no reviewer can evaluate it. A review of the grants issued in the last 30 days, each with a stated purpose, is a few hundred lines and can actually be read.
Implementation patterns
- Build the issuing path before revoking anything. If re-requesting takes a day, analysts will hoard access through any mechanism available. A self-service request that returns a grant in minutes is the precondition, not a refinement.
- Run it in shadow mode first: auto-approve everything with a 30-day expiry and measure request volume. You are sizing the queue, not enforcing policy.
- Tier by sensitivity label. Internal and below auto-approve with expiry; only Restricted reaches a human. Skipping the tiering turns the pattern into an approval queue nobody can staff.
- Expire the derived objects too. A materialised view, scheduled report or BI extract created under a grant keeps serving rows after the grant lapses, because it runs as its owner. Tie the object's schedule to the grant, or reconcile objects against current entitlements weekly.
- Record purpose as a selection, not free text. A closed list of purposes is queryable; a text box produces "analysis" 4,000 times.
- Keep an audited break-glass path with a short expiry and a mandatory review, because an incident at 3 a.m. must not wait for an approver.
Industry example
Twitch attributed its October 2021 exposure to an error in a server configuration change, and what left included source code, internal tooling and creator payout reports covering 2019 to 2021. The detail worth carrying into a data platform is that the exposure included artefacts produced under access, not only primary records. A just-in-time model that expires grants while leaving every report, extract and materialised view built under them untouched shrinks the entitlement list and not the blast radius, which is the mistake that makes the programme look successful on a dashboard.
Failure scenarios
- Expiry without a fast re-request path. Analysts build private copies of data to avoid the friction, and the estate acquires an ungoverned shadow layer that no policy reaches.
- Approval on everything. Median queue time rises past a day, and the pattern is blamed for slowing the business when the tiering was the missing piece.
- Purpose collected and never queried. It becomes a field, not a control, and satisfies nobody when a regulator asks what the data was used for.
- Legacy groups deleted before two full expiry cycles. Group membership was the only record of who held what, and there is now no way to reconstruct an entitlement that turns out to have been needed.
- Service accounts exempted permanently because they are "not people", which is where most of the standing access ends up.
Trade-offs
| Choose | Gains | Pays |
|---|---|---|
| Just-in-time grants | Blast radius decays by default; reviewable access history with purpose | A self-service path to build and run; friction on every genuinely new question |
| Standing grants | Zero friction after the first request | An entitlement list that only grows and an access review nobody can meaningfully perform |
The friction is real and it is the point. The design question is where to put it: on the 10% of requests touching Restricted data, or evenly across everything, which is how the pattern acquires a bad reputation.
When not to use it
Below roughly 50 analysts with a single sensitivity tier, this is ceremony. Record the purpose in the request ticket, keep standing grants, and spend the effort on query-level audit instead, which buys most of the evidence at a fraction of the cost. It is also the wrong tool when the real problem is that too many people can see one table: that is a modelling and masking problem, and adding expiry to an over-broad grant just means it is re-issued every 30 days.
Interview question
Q: You have four years of accumulated standing grants across 900 analysts and legal now requires time-boxed access with recorded purpose. Sequence the migration, and tell me where data can still leak after every grant has expired.
What a strong answer covers: audit before revoking, and the 60% to 80% of unused pairs that finding usually yields; standing the issuing path up before any revocation; shadow mode to size the queue; revoking the unused set first because it is reversible in minutes; tiering by sensitivity so approvals stay scarce; deleting legacy groups last as the point of no return; and the derived-object gap, where scheduled reports and extracts keep serving rows under an owner's identity after the reader's grant has gone.
Quick check
Quiz: What does just-in-time access add that purpose-based access does not? A duration. Purpose answers why the data may be used; expiry answers who can read it today, and it is expiry that makes the blast radius shrink without anyone running a project.
Flashcard: Every standing grant on a Restricted table has expired and the access review is clean. What still returns those rows? Materialised views, scheduled reports and BI extracts created while the grant was live, because they execute as their owner or a service principal rather than as the reader.