Structuring Cloud Firestore Security Rules

Cloud Firestore Security Rules allow you to control access to documents andcollections in your database. The flexible rules syntax allows you to createrules that match anything, from all writes to the entire database to operationson a specific document.

This guide describes the basic syntax and structure of security rules. Combinethis syntax withsecurity rules conditions to createcomplete rulesets.

Note: The server client libraries bypass allCloud Firestore Security Rules and instead authenticate throughGoogle Application Default Credentials. If you're using the server client libraries or the REST or RPC APIs, make sure to set upIdentity and Access Management (IAM) forCloud Firestore.

Service and database declaration

Cloud Firestore Security Rules always begin with the following declaration:

service cloud.firestore {  // The {database} wildcard allows the rules to reference any database,  // but these rules are only active on databases where they are explicitly deployed.  match /databases/{database}/documents {    // ...  }}

Theservice cloud.firestore declaration scopes the rules toCloud Firestore, preventing conflicts betweenCloud Firestore Security Rules andrules for other products such as Cloud Storage.

Thematch /databases/{database}/documents declaration specifies that rulesshould match anyCloud Firestore database in the project. While a projectcan contain up to 100 databases, only the first database created is designatedas the default.

Cloud Firestore Security Rules are applied separately for each named database in your project.This means that if you create multiple databases, you must manage and deployrules for each one individually.For detailed instructions on deploying your updates, seeDeploy your updates.

Basic read/write rules

Basic rules consist of amatch statement specifying a document path andanallow expression detailing when reading the specified data is allowed:

servicecloud.firestore{match/databases/{database}/documents{//Matchanydocumentinthe'cities'collectionmatch/cities/{city}{allowread:if<condition>;allowwrite:if<condition>;}}}

All match statements should point to documents, not collections. A matchstatement can point to a specific document, as inmatch /cities/SF or use wildcardsto point to any document in the specified path, as inmatch /cities/{city}.

In the example above, the match statement uses the{city} wildcard syntax.This means the rule applies to any document in thecities collection, such as/cities/SF or/cities/NYC. When theallow expressions in the match statement areevaluated, thecity variable will resolve to the city document name,such asSF orNYC.

Note: You can only access documents that your security rules specifically allowyou to access. For example, the rules shown above allow access only to documentsin thecities collection; as a result, they also deny access to documents inall other collections.

Granular operations

In some situations, it's useful to break downread andwrite into moregranular operations. For example, your app may want to enforce differentconditions on document creation than on document deletion. Or you may want toallow single document reads but deny large queries.

Aread rule can be broken intoget andlist, while awrite rule canbe broken intocreate,update, anddelete:

servicecloud.firestore{match/databases/{database}/documents{//Areadrulecanbedividedintogetandlistrulesmatch/cities/{city}{//Appliestosingledocumentreadrequestsallowget:if<condition>;//Appliestoqueriesandcollectionreadrequestsallowlist:if<condition>;}//Awriterulecanbedividedintocreate,update,anddeleterulesmatch/cities/{city}{//Appliestowritestononexistentdocumentsallowcreate:if<condition>;//Appliestowritestoexistingdocumentsallowupdate:if<condition>;//Appliestodeleteoperationsallowdelete:if<condition>;}}}

Hierarchical data

Data inCloud Firestore is organized into collections of documents, and eachdocument may extend the hierarchy through subcollections. It is important tounderstand how security rules interact with hierarchical data.

Consider the situation where each document in thecities collection contains alandmarks subcollection. Security rules apply only at the matched path, so theaccess controls defined on thecities collection do not apply to thelandmarks subcollection. Instead, write explicit rules to control accessto subcollections:

servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}{     allowread,write:if<condition>;//Explicitlydefinerulesforthe'landmarks'subcollection       match/landmarks/{landmark}{         allowread,write:if<condition>;     }   } }}

When nestingmatch statements, the path of the innermatch statement is alwaysrelative to the path of the outermatch statement. The following rulesetsare therefore equivalent:

servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}{   match/landmarks/{landmark}{     allowread,write:if<condition>;     }   } }}
servicecloud.firestore{ match/databases/{database}/documents{   match/cities/{city}/landmarks/{landmark}{   allowread,write:if<condition>;   } }}

Recursive wildcards

If you want rules to apply to an arbitrarily deep hierarchy, use therecursive wildcard syntax,{name=**}. For example:

servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthecitiescollectionaswellasanydocument//inasubcollection.match/cities/{document=**}{allowread,write:if<condition>;}}}

When using the recursive wildcard syntax, the wildcard variable will contain theentire matching path segment, even if the document is located in a deeply nestedsubcollection. For example, the rules listed above would matcha document located at/cities/SF/landmarks/coit_tower, and the value ofthedocument variable would beSF/landmarks/coit_tower.

Note, however, that the behavior of recursive wildcards depends on the rulesversion.

Version 1

Security rules use version 1 by default. In version 1, recursive wildcardsmatch one or more path items. They do not match an empty path, somatch /cities/{city}/{document=**} matches documents in subcollections butnot in thecities collection, whereasmatch /cities/{document=**} matchesboth documents in thecities collection and subcollections.

Recursive wildcards must come at the end of a match statement.

Version 2

In version 2 of the security rules, recursive wildcards match zero or more pathitems.match/cities/{city}/{document=**} matches documents in anysubcollections as well as documents in thecities collection.

You must opt-in to version 2 by addingrules_version = '2'; at the top ofyour security rules:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthecitiescollectionaswellasanydocument//inasubcollection.match/cities/{city}/{document=**}{allowread,write:if<condition>;}}}

You can have at most one recursive wildcard per match statement, but in version2, you can place this wildcard anywhere in the match statement. For example:

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthesongscollectiongroupmatch/{path=**}/songs/{song}{allowread,write:if<condition>;}}}

If you usecollection group queries, you must useversion 2, seesecuring collection group queries.

Overlapping match statements

It's possible for a document to match more than onematch statement. In thecase where multipleallow expressions match a request, the access is allowedifany of the conditions istrue:

servicecloud.firestore{match/databases/{database}/documents{//Matchesanydocumentinthe'cities'collection.match/cities/{city}{allowread,write:iffalse;}//Matchesanydocumentinthe'cities'collectionorsubcollections.match/cities/{document=**}{allowread,write:iftrue;}}}

In the example above, all reads and writes to thecities collection will beallowed because the second rule is alwaystrue, even though the firstrule is alwaysfalse.

Security rule limits

As you work with security rules, note the following limits:

LimitDetails
Maximum number ofexists(),get(), andgetAfter() calls per request
  • 10 for single-document requests and query requests.
  • 20 for multi-document reads, transactions, and batched writes. The previous limit of 10 also applies to each operation.

    For example, imagine you create a batched write request with 3 write operations and that your security rules use 2 document access calls to validate each write. In this case, each write uses 2 of its 10 access calls and the batched write request uses 6 of its 20 access calls.

Exceeding either limit results in a permission denied error.

Some document access calls may be cached, and cached calls do not count towards the limits.

Maximum nestedmatch statement depth10
Maximum path length, in path segments, allowed within a set of nestedmatch statements100
Maximum number of path capture variables allowed within a set of nestedmatch statements20
Maximum function call depth20
Maximum number of function arguments7
Maximum number oflet variable bindings per function10
Maximum number of recursive or cyclical function calls0 (not permitted)
Maximum number of expressions evaluated per request1,000
Maximum size of a rulesetRulesets must obey two size limits:
  • a 256 KB limit on the size of the ruleset text source published from theFirebase console or from the CLI usingfirebase deploy.
  • a 250 KB limit on the size of the compiled ruleset that results when Firebase processes the source and makes it active on the back-end.

Next steps

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-18 UTC.