Search code examples
firebasegoogle-cloud-firestorefirebase-security

Cacheing of Firestore Security Rules get()


I want to know the extent that firestore caches security rule evaluations of get() lookups when executing a query or across queries. I feel that the docs, while they do mention cacheing occurs, do not detail the specifics of when it happens or how queries incur particular read costs.

My question is therefore is, on a given query where many documents are requested, will an applicable firestore rule always cache results of get() if that get() is to the same document across the query?

For instance, I have an image collection where each image doc should logically belong to a project (ie project field in the doc). I want an image doc to be secured such that its viewed only by people who are "assigned" to that project, so i structure my data like this:

images collection:

"imgxyz": {
  name: "img1",
  url: "xyz.com",
  snapshot:"bbb",
  project: "aaa",
}
"imgzyx": {
  name: "img2",
  url: "zyx.com",
  snapshot:"bbb",
  project: "aaa",
}

users collection:

"uid1": {
  userName: "img2",
  email: "zyx.com",
  projects: ["aaa","bbb"],
}

then the rules:

service cloud.firestore {
  match /databases/{database}/documents {
  
    function canViewImage() {
    
        let userProjects = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.projects;
        let requestedDocProject = request.resource.data.project;
        return requestedDocProject in userProjects;
    }
  }
}

with the above, how would a query like .where("snapshot", "==", "bbb") perform from a security rules cost standpoint, if query-matched image docs were in the thousands? Would I incur just 1 additional read for the get() lookup of the user, provided to all rule evals of the image doc? or would it be equal to the amount of image docs.

Further, what if the queries were individually called, ie .get("imgxyz") then right after .get("imgzyx"), how would the cacheing work then?

note: i saw this question, but didnt feel that it sufficeintly explained when/why security rules would cache results.

Thank you in advance!


Solution

  • will an applicable firestore rule always cache results of get() if that get() is to the same document across the query?

    Yes.

    with the above, how would a query like .where("snapshot", "==", "bbb") perform from a security rules cost standpoint, if the retrieved image docs were in the thousands?

    No, security rules are not filters. They don't check all documents. A rule that looks like a filter (when making a query that could match multiple documents) actually just requires that a matching filter be present on the client query, which uses an index to avoid reading every document.

    In more common sense terms: it would be completely unacceptable in terms of query performance guarantees for a rule to actually read and consider every single potentially matching document in a query. That's why it just considers the query filters.

    Further, what if the queries were individually called, ie .get("imgxyz") then right after .get("imgzyx"), how would the cacheing work then?

    No, there is no caching between queries. The rules have no idea if the underlying data may have changed between queries, so it has to check each document again for each query in order to ensure consistency for each query.