When I started digging into how Supabase handles PostgreSQL reads, something kept showing up in the logs that didn’t feel quite right on the surface. Identical .select() queries firing over and over again — triggered by navigation, hydration, multiple tabs, React rerenders, router prefetching, and every other natural quirk of modern frontends.
It’s the classic pattern every SPA and SSR app has lived with for years, but it raises a question:
“If the data hasn’t changed, why doesn’t Supabase just cache the read?”
This question usually appears after someone gets surprised by egress usage or sees a spike in rpc calls for read-heavy pages. And the temptation is to assume that Supabase could solve this with a toggle: “smart caching,” “automatic caching,” “cache identical queries,” etc.
1. Automatic caching breaks the moment you introduce RLS
PostgREST applies Row Level Security for every request.
Even two requests that look identical in URL form:
/rest/v1/orders?user_id=eq.42
may produce different results depending on:
- JWT claims
- authenticated user
- active roles
- policy filters
- session context
There is no “same query” in a multi-tenant, policy-protected system.
Auto-caching at the platform layer risks returning the wrong user’s data — which is a correctness failure, not a performance regression.
This alone eliminates the idea of transparent caching.
2. PostgreSQL is not a document store and doesn’t behave like one
The Firebase mental model (“data is a tree; cache the path”) simply does not translate to SQL.
PostgreSQL views, joins, computed columns, and filtered selects all make it nearly impossible to determine cache keys automatically.
Caching is an application concern, not a database-adapter concern.
3. Staleness budgets are product decisions, not platform decisions
Some data models tolerate seconds of staleness.
Some tolerate milliseconds.
Some tolerate none.
Supabase cannot infer which category your endpoint falls into.
Caching PostgreSQL reads without explicit developer intent is reckless — the database layer cannot safely decide correctness on your behalf.
4. Modern frontends will generate redundant reads by design
This isn’t a Supabase problem.
It’s a framework behavior.
React hydration, prefetching, tab duplication, visible → hidden visibility events, and router-level transitions all produce legitimate-but-redundant queries.
Every database adapter suffers from this.
Supabase simply exposes the truth in the logs.
Caching isn’t a fix for frontend behavior — deduplication and memoization in the application layer are.
5. Supabase does give you the right caching primitives, but intentionally avoids magic
Supabase offers caching, but all of it is opt-in:
- HTTP caching via Cache-Control
- Next.js server component memoization
- React Query stale-while-revalidate patterns
- KV/Redis for explicit caching when needed
This is deliberate.
Caching is safe only when the developer defines:
- the staleness window
- the cache key
- the invalidation strategy
Anything automatic would violate correctness guarantees.
The Real Point: Supabase Trades “Magic” for “Predictability”
Supabase could add a toggle tomorrow:
“Cache identical reads for N seconds.”
But it would produce nondeterministic correctness issues the moment RLS, session context, or multi-tenant data enters the picture.
Supabase chooses predictable behavior over premature optimization.
That’s not a limitation — it’s the right engineering decision.
What We should optimize instead
If you’re building on Supabase, the real wins come from:
- deduping reads at the framework level (RSC memoization, React Query, SWR)
- controlling staleness budgets explicitly
- designing your data model with read patterns in mind
- understanding where user-specific filtering intersects with caching
- using CDN caching for public or shared data
Supabase handles the PostgREST layer correctly.
It’s up to the application to avoid redundant reads caused by the frontend environment.
Final Thought
Supabase’s job is to be correct — not clever.
PostgreSQL + RLS + policy-based access means there is no such thing as “automatic caching” that wouldn’t eventually break someone’s app.
Supabase gives you the primitives.
You make the rules.
That’s the right separation of responsibilities for any serious application.
Top comments (0)