According to documentation, I should
# spicedb
k
According to documentation, I should store a ZedToken every time I make a change to an object or a relation. And then I'll be able to efficiently check permission using data as recent as said ZedToken. Sounds fair to me. My question is: say I want to check access for a user against a resource, do I have to store ZedTokens of the user and the resource and use the more recent of the two? What is the recommendation in this case?
v
You should only store the zedtoken of the user if you have a user-case where the user can become the resource of a request (think "can user A view profile of User B?). To perform a request of a user over a given resource, you need to use the zedtoken of the resource.
k
Thanks, what if the user has just gained access to a resource? Wouldn't their ZedToken be more recent than the resource's ZedToken?
Oh nvm, in that case I would just store the zedtoken on the resource wouldn't I?
v
If the user has just gained access to the resource, I'd expect there was a new relationship added to the resource, or to some indirect resource (e.g. team), instead of a change to the user, unless your model is somehow inverted
k
Understood. If the user was added to a team, I would want to check permission with the team's ZedToken instead of the resource right?
v
If you wanted to observe the change yes, but is that a requirement in your application?
Typically folks use the zedtoken for read-your-write consistency. The most common scenario is a resource is created and you redirect them to the resource: if you don't use that zedtoken, SpiceDB is likely to return indicate the user has no permission and cause the page to render with 403, which is a jarring experience for the user. But in the case of being asses to a team, is the expectation to immediately see the effects of it?
k
So actually we're building an OTT service where the users are able to watch videos based on their subscription. From trying out the schema language, it seems that all permission-checking paths go through the subscription plan object type. So that means I want to store the ZedTokens of each subscription plan object and use them whenever I want to check for permission right? Just for clarification below is the schema I'm writing.
/** user represents a registered user's account */ definition user {} /** anonymoususer represents an unauthenticated user */ definition anonymoususer {} /** * studio_profile represents a studio profile on the app that owns contents that users can watch */ definition studio_profile { relation viewer: anonymoususer:* | user:* | subscription_plan#subscriber permission view = viewer } definition collection { relation studio_profile: studio_profile relation viewer: anonymoususer:* | user:* | subscription_plan#subscriber permission view = viewer + studio_profile->view } /** vod represents a video-on-demand (movies or otherwise) */ definition vod { relation studio_profile: studio_profile relation collection: collection relation viewer: anonymoususer:* | user:* | subscription_plan#subscriber permission view = viewer + studio_profile->view + collection->view } definition subscription_plan { relation subscriber: user }
v
It depends on your application access patterns. The recommendation is to store the corresponding zedtoken of each resource along each entry in your main DB. If you don't care about new enemy problem / read-your-writes consistency, you can probably fare just fine without then and do
minimize_latency
consistency. So if you cared about read-your-write/new enemy, storing the zedtoken when the subscription changes woudn't work, but if you stored the zedtoken of each data change that hangs from the subscription in the subscription, then it would work, but that sounds like a potential write amplification problem (e.g. a studio adds a new video, and 1M subscriptions have to be updated 🙈)
I'd say start building an MVP with
minimize_latency
and no zedtokens. Once you have a better picture of your access patterns and whether you can live with eventual consistency or not, evaluate adding zedtokens to your DB.
k
Hmm, a subscription plan is shared by all the subscribers of that plan rather than 1 plan per subscriber so I don't think there will be write amplification.
The entire system would just have like 3 subscription plans that get updated very frequently whenever a new user subscribe or new content/studio/collection is added to that plan. So I don't think it would be particularly bad?
v
if it's "updated very frequently" it sounds like it would cause row contention in your DB (the same row updated over and over), but I'd say go for it and see how it fares.
k
Thanks a lot! That helped
v
anytime!