Introduction
Firebase Firestore is an exceptional database choice for building rapidly scaling applications. However, because client applications query Firestore collections directly, defining robust security layers at the database level is critical.
In this guide, we will analyze Firestore Security Rules architecture to write granular, cost-efficient security declarations.
The Foundation of Firestore Rules
Security Rules execute on Firestore servers before database documents are accessed or modified. They are written in a custom DSL (domain-specific language) matching paths using resource matches:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}This standard rule grants authenticated users read and write access only to their dedicated document inside the users collection.
Advanced Data Validation Patterns
In real-world applications, writes often depend on complex conditions, such as user roles, subscription states, or field formats.
Let's look at validation patterns to secure an event sign-up collection:
match /registrations/{registrationId} {
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid
&& request.resource.data.status == 'pending'
&& request.resource.data.createdAt == request.time;
}request.resource.data: Represents the pending document data about to be written. We enforce that the writer matches the authenticated user and forces a pending registration state.request.time: Enforces that the client-submitted timestamp matches the Firestore server's actual time, preventing client spoofing.
Performance and Firestore Billing Rules
Firestore Security Rules run inside database execution pipes. Some checks—like calling get() or exists() to read helper documents—trigger standard Firestore read operations:
- Rules Billing: Every custom
get()call in your security rules counts as a standard Firestore document read, which increases billing costs. - Rules Limits: Rules are capped at a maximum of 10 external read operations per client query request.
To avoid billing bloat, bundle user status flags directly inside custom JWT claims (using Firebase Auth Custom Claims) so they can be read immediately using the request.auth.token context without querying Firestore.
Conclusion
Securing your database collections does not have to result in complex architectures. By leveraging strict validation checks and user auth tokens, you keep Firestore fast, affordable, and fully protected.

