
Cloud Firestore is one of the NoSQL databases provided by Firebase for storing application data.
Cloud Firestore is a flexible, scalable database for server, mobile, and web development. It keeps data synchronized across clients, supports offline work, and integrates smoothly with the wider Firebase and Google Cloud ecosystem.
For a long time it lived in beta, but even then it was already robust enough to support real applications. Still, as with any database, the long-term outcome depends heavily on the quality of the data model.
That matters even more in Firestore: a good structure makes the system easier to query and secure, while a poor structure can turn simple features into a constant source of friction.
What Cloud Firestore gives us
Cloud Firestore is a document-oriented database. If you have already worked with systems such as MongoDB, the overall model will feel familiar.
Its structure is based on:
- collections, which group entities of the same kind,
- documents, which live inside those collections,
- and fields, which hold the attributes of each document.
Each collection has a name. Each document has a unique identifier. And one important detail is that sibling documents do not need to share exactly the same set of fields, even though in practice we usually want a reasonably consistent shape.
Getting started in Firebase
Because Firestore belongs to the Firebase ecosystem, the first step is to sign in with a Google account:
https://console.firebase.google.com/
From there we can create a new project or reuse an existing one. If we create a new project, Firebase asks for a name and a region.
That region is not a trivial detail. It can affect latency, pricing, and compliance concerns such as data residency requirements.
Once the project exists, the Firebase dashboard gives access to all associated services. To open Firestore, go to Database and choose Cloud Firestore.
At that point Firebase also asks for an initial security mode. A sensible default is locked mode, which blocks access until we define proper rules.
Once inside Firestore
When we enter Firestore we see several tabs, but the two that matter most at the beginning are:
- Data
- Rules
The data tab reflects the core model directly: collections contain documents, and documents contain fields.
For example, a users collection may contain individual user documents. If we query users, we target the collection. If we query users/{id}, we target one concrete document.
Inside a document we can store primitive values, objects, and also subcollections.
What subcollections are and when to use them
A subcollection is a collection nested inside a specific document. That means it belongs to that document and is accessed through that document’s identifier.
For example:
/users/{userId}/[subcollection-name]
A very common question is this:
What does a subcollection give us that a plain object field does not?
The most practical answer is permissions and access boundaries. If a client has permission to read users/{userId}, it can read everything directly stored in that document. A subcollection, on the other hand, can be protected with more specific rules and consumed separately.
That makes it useful for data that should not automatically travel together with the parent document, or data that should only be accessible to a narrower audience.
Rules
Rules are one of Firestore’s strongest features. They let us define who can access which routes and what actions are allowed on each route.
Firestore exposes data through a route-oriented structure, which makes access control very expressive.
The default initial configuration is essentially a full deny:
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
In other words, every read and write is blocked until we explicitly allow it.
The main actions we can control are:
createreadupdatedelete
And we can combine them according to route and condition.
The official security documentation covers those basics in more depth:
https://firebase.google.com/docs/firestore/security/get-started?hl=es-419
More advanced rules
Rules are not limited to statically opening or closing a route. They can also express richer logic based on the request and on stored data.
Imagine a users collection where each document contains a roles object with boolean flags such as:
roles.subscriber
roles.editor
roles.admin
With that model we can decide that:
subscribercan only read,editorcan update,adminis the only role allowed to create and delete.
The general idea is to rely on request.auth.uid, fetch the document for the user making the request, and inspect the stored roles before authorizing the operation.
The mental model looks something like this:
allow read: if hasRole('subscriber');
allow update: if hasRole('editor');
allow create, delete: if hasRole('admin');
On top of that, we can still add a condition requiring the user to be authenticated before any role check even runs.
Conclusion
Cloud Firestore is an extremely capable database with a very clean structure and configuration model. When designed well, it can dramatically speed up the development of small and medium-sized applications.
The important thing is not to treat it as a random bucket of documents. It is worth spending time deciding:
- how to split collections and documents,
- when to use subcollections,
- and how to express permissions through rules.
When that foundation is sound, the rest of the application becomes much easier to evolve.