Cache Authorization
Your database decides which users may read which tables, and it re-checks those grants on every query. A shallow cache hit is answered by Readyset without reaching your database, so without extra care a cache would let a user keep reading a query after their access to the underlying tables was revoked.
Cache authorization prevents that. Before Readyset serves a cache hit, it confirms that the connected user is still allowed to run that query. Users who are allowed are served from the cache as usual; users who are not are sent to your database, exactly as if the query were uncached.
Cache authorization is on whenever authentication is enabled. There is nothing to configure and no opt-out, and it adds no latency to a cache hit.
What a user sees
Whether a given user is served from a cache depends only on whether your database grants that user access to the query:
- Allowed users get cache hits, at the same hit rate as before. A user's identity never affects what is stored, so enabling cache authorization does not shrink or partition the cache.
- Users without access are transparently routed to your database, which applies its own permission check and returns the appropriate result or error. They simply never get a cache hit for that query.
Because an unauthorized user is always sent to your database rather than guessed at, cache authorization can never turn a permitted query into an error or an error into data. Your database stays the single source of truth for who may read what; Readyset only mirrors its decisions and never reimplements grants, roles, or inheritance.
Readyset learns each user's access by asking your database, on its own
background connections, whether that user could run the cached query -- without
actually running it. These connections identify themselves as
READYSET_ACL_POOLER in your database's process list. No client connection is
ever used for this, and no check ever runs while a query is being served.
Keeping up with privilege changes
Readyset re-reads each user's privileges from your database on a fixed
interval (default 5 minutes, set with
--cache-acl-refresh-interval-secs).
This interval is the longest a user can keep being served cache hits after a
GRANT or REVOKE you issue directly on your database -- the same kind of
staleness window a cache already has for data via its TTL. A user who is
newly granted access converges just as quickly; until Readyset picks up the
change, their queries are simply proxied to your database.
Some changes take effect immediately, without waiting for the interval:
- Creating a cache authorizes every user against it in the background, starting with its creator. Creating a cache is not itself a grant: the creator is served from it only once their own privileges check out, the same as everyone else.
ALTER READYSET ADD/MODIFY USERre-checks that user;DROP USERforgets them. See User Management.ALTER READYSET FLUSH PRIVILEGESre-checks everyone on demand. Run it right after aGRANTorREVOKEon your database to apply the change without waiting for the next interval.
Roles
PostgreSQL
PostgreSQL evaluates privileges against a session's current role, and cache
authorization follows the same rule. A session that has switched roles with
SET ROLE is judged by that role's access, not the login user's. Readyset
does not decide role membership itself: a SET ROLE is forwarded to your
database on the session's own connection, and the session's identity changes
only if your database accepts it. Roles are authorized ahead of use, so
assuming a role does not cost a warm-up period.
MySQL
On MySQL, a user is authorized under their default roles -- the same
privileges a fresh connection gets. Users whose access comes through roles are
fully supported as long as those roles are active by default (via
SET DEFAULT ROLE or activate_all_roles_on_login=ON).
A session that changes its active roles with SET ROLE mid-connection is not
served from the cache for the rest of that connection; its queries are proxied
to your database, which enforces privileges directly. Sessions that rely on
mid-connection role switching trade away caching on MySQL for now.
Inspecting cache authorization
The readyset.cache_grants
system view shows, for every user and cache, whether that user is currently
served from it and when Readyset last checked. Prometheus metrics under the
readyset_cache_acl prefix cover the same ground for dashboards, including how
often queries are routed to your database instead of served from a cache.
For a single connection,
EXPLAIN LAST STATEMENT reports
why its previous statement went to your database instead of a cache: a
Readyset_reason of cache_acl_denied or cache_acl_unknown means cache
authorization made the call.
Limitations
- Cache authorization applies to shallow caches
on both MySQL and PostgreSQL. It does not apply under
--allow-unauthenticated-connections, where there are no user identities to authorize. - It enforces table-level grants. Row-level security is handled separately by Readyset's RLS-aware caching, which composes with cache authorization.
SHOW CACHESlists the query text of every cache, including caches over tables a user cannot read.