Storing Read-Only User Data in Sanity Data Store
Great question! This is something that comes up often, and I'd recommend not storing end-user application data (like user profiles, progress tracking, or authentication details) directly in Sanity's Content Lake. Here's why:
Why Sanity isn't ideal for end-user data
1. It's designed for content, not application data Sanity is built as a Content Operating System - it excels at managing editorial content, structured data that powers your website/app experiences, and assets. It's not optimized for the high-frequency read/write patterns typical of user data (think progress tracking, user sessions, activity logs).
2. Access control limitations While Sanity has Custom Roles for Enterprise plans that allow document-level permissions using GROQ filters, these are primarily designed for content team workflows (like restricting editors to certain content areas), not for isolating individual end-user data. There's no built-in per-user document isolation for application users.
3. Dataset privacy considerations As mentioned in the security docs, even with private datasets, asset files remain publicly accessible. If you're storing user profile images or other assets, they wouldn't be truly private.
4. PII and compliance concerns Storing personally identifiable information (PII) in Sanity requires careful consideration. While Sanity is GDPR and SOC2 compliant, you'd need to manage data retention, deletion requests, and privacy controls yourself - which is much easier with a traditional user database.
The recommended approach
Use PostgreSQL + Prisma for user data, Sanity for content
This is exactly the right instinct! Keep your architecture separated:
- PostgreSQL/Prisma: User accounts, authentication, progress tracking, user-generated data, anything that's user-specific or changes frequently
- Sanity: Editorial content, courses/lessons structure, media assets, anything your content team manages
This gives you:
- Proper authentication patterns (NextAuth, Clerk, Auth0, etc. integrate seamlessly with Postgres)
- Row-level security for user data isolation
- Better performance for user-specific queries
- Easier GDPR compliance and data deletion
- Standard relational patterns for user progress tracking
How to connect them
You can reference Sanity content from your user database using document IDs. For example:
// In your Postgres schema (Prisma)
model UserProgress {
id String @id
userId String
sanityContentId String // Reference to Sanity document
completed Boolean
lastAccessed DateTime
}Then query Sanity content separately and join in your application layer.
When you might use Sanity for user-related data
The only exception would be if you're building something like a community platform where user-generated content becomes editorial content that needs to be moderated, structured, and published. Even then, you'd typically store the core user account data elsewhere and only sync approved content into Sanity.
Your PostgreSQL + Prisma approach is the right call here. Keep Sanity for what it does best - being your content backend - and use a proper user database for application user data.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.