Skip to main content
RapidDev - Software Development Agency
firebase-tutorial

How to Restore Firestore from a Backup

Restore Firestore data from a backup using the gcloud firestore import command pointed at a Google Cloud Storage bucket containing a previous export. For full database restores, run gcloud firestore import gs://your-bucket/export-folder. For selective collection restores, add the --collection-ids flag. Firebase also offers Point-in-Time Recovery (PITR) on Blaze plan databases, which lets you restore to any second within the last 7 days without needing a prior export.

What you'll learn

  • How to restore Firestore from a gcloud export backup
  • How to restore specific collections instead of the entire database
  • How to use Point-in-Time Recovery (PITR) for recent data loss
  • How to verify the restored data and avoid common restore pitfalls
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read15-20 minFirebase Blaze plan, gcloud CLI, Firestore (Native mode)March 2026RapidDev Engineering Team
TL;DR

Restore Firestore data from a backup using the gcloud firestore import command pointed at a Google Cloud Storage bucket containing a previous export. For full database restores, run gcloud firestore import gs://your-bucket/export-folder. For selective collection restores, add the --collection-ids flag. Firebase also offers Point-in-Time Recovery (PITR) on Blaze plan databases, which lets you restore to any second within the last 7 days without needing a prior export.

Restoring Firestore Data from Backup

Accidental data deletion, bad deployments, or security rule misconfiguration can corrupt your Firestore data. If you have a previous backup created with gcloud firestore export, you can import it back into your database. This tutorial walks through restoring from a Cloud Storage backup, restoring specific collections, using PITR for recent incidents, and verifying the restore completed correctly.

Prerequisites

  • A Firebase project on the Blaze plan
  • Google Cloud CLI (gcloud) installed and authenticated
  • A previous Firestore export in a Google Cloud Storage bucket
  • IAM roles: Cloud Datastore Import Export Admin and Storage Admin

Step-by-step guide

1

Locate your backup in Cloud Storage

Before restoring, identify the backup you want to import. Firestore exports are stored in Google Cloud Storage buckets as folders containing metadata files and document data. List the contents of your backup bucket to find the export folder. Each export creates a folder with a timestamp or name you specified during the export. The folder contains an overall_export_metadata file that the import command needs.

typescript
1# List all exports in your backup bucket
2gcloud storage ls gs://your-backup-bucket/
3
4# List contents of a specific export folder
5gcloud storage ls gs://your-backup-bucket/2026-03-28-daily-backup/
6
7# You should see an overall_export_metadata file
8# gs://your-backup-bucket/2026-03-28-daily-backup/overall_export_metadata
9# gs://your-backup-bucket/2026-03-28-daily-backup/all_namespaces/

Expected result: You can see the export folder contents including the overall_export_metadata file, confirming the backup is valid.

2

Restore the full database from backup

Run the gcloud firestore import command with the path to the export folder (not the metadata file itself). The import is a long-running operation — it runs in the background on Google's servers and can take minutes to hours depending on the database size. The command returns an operation ID you can use to check progress. Important: importing does NOT delete existing documents that are not in the backup. It overwrites documents that exist in both the backup and the live database.

typescript
1# Import the full backup
2gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup
3
4# The command outputs an operation ID like:
5# operation: projects/your-project/databases/(default)/operations/abc123
6
7# Check import progress
8gcloud firestore operations describe projects/your-project/databases/(default)/operations/abc123

Expected result: The import operation starts and runs in the background. The describe command shows the operation status as RUNNING or DONE.

3

Restore specific collections only

If you only need to restore certain collections rather than the entire database, use the --collection-ids flag. This is useful when a bug corrupted one collection but the rest of your data is fine. You can specify multiple collection IDs separated by commas. The export must have been created without collection filters (a full export) or must include the collections you want to restore.

typescript
1# Restore only the 'users' and 'orders' collections
2gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup \
3 --collection-ids=users,orders
4
5# Restore a single collection
6gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup \
7 --collection-ids=products

Expected result: Only the specified collections are restored from the backup. Other collections in the database remain unchanged.

4

Use Point-in-Time Recovery (PITR) for recent data loss

If the data loss happened within the last 7 days and your database has PITR enabled, you can restore to any second within that window without needing a prior export. PITR is available on Blaze plan and must be enabled before the incident occurs. Use the Firebase Console or gcloud to initiate a PITR restore to a new database, then migrate the data back to your primary database.

typescript
1# Check if PITR is enabled on your database
2gcloud firestore databases describe --database="(default)"
3
4# Enable PITR (must be done BEFORE data loss occurs)
5gcloud firestore databases update --database="(default)" \
6 --enable-pitr
7
8# Restore to a point in time (creates a new database)
9# Use ISO 8601 timestamp format
10gcloud firestore databases restore \
11 --source-database="(default)" \
12 --destination-database="restored-db" \
13 --snapshot-time="2026-03-27T14:30:00Z"

Expected result: A new database named 'restored-db' is created containing the exact state of your data at the specified timestamp.

5

Verify the restored data

After the import operation completes, verify the data was restored correctly. Check document counts in key collections, spot-check specific documents, and test your application against the restored data. If you restored specific collections, verify that only those collections were affected and that other data remains intact.

typescript
1import { initializeApp } from 'firebase/app'
2import { getFirestore, collection, getCountFromServer, doc, getDoc } from 'firebase/firestore'
3
4const app = initializeApp({ /* your config */ })
5const db = getFirestore(app)
6
7async function verifyRestore() {
8 // Check document counts
9 const usersCount = await getCountFromServer(collection(db, 'users'))
10 console.log('Users collection count:', usersCount.data().count)
11
12 const ordersCount = await getCountFromServer(collection(db, 'orders'))
13 console.log('Orders collection count:', ordersCount.data().count)
14
15 // Spot-check a specific document
16 const testDoc = await getDoc(doc(db, 'users', 'known-user-id'))
17 if (testDoc.exists()) {
18 console.log('Test user data:', testDoc.data())
19 } else {
20 console.warn('Test user document not found — restore may be incomplete.')
21 }
22}

Expected result: Collection counts match expected values from the backup, and spot-checked documents contain the correct data.

Complete working example

restore-verification.ts
1import { initializeApp } from 'firebase/app'
2import {
3 getFirestore,
4 collection,
5 getCountFromServer,
6 doc,
7 getDoc,
8 getDocs,
9 query,
10 limit,
11 orderBy
12} from 'firebase/firestore'
13
14const app = initializeApp({
15 apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!,
16 authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN!,
17 projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!
18})
19
20const db = getFirestore(app)
21
22interface RestoreVerification {
23 collection: string
24 count: number
25 sampleDoc: Record<string, any> | null
26}
27
28async function verifyCollectionRestore(
29 collectionName: string
30): Promise<RestoreVerification> {
31 // Get total document count
32 const countResult = await getCountFromServer(
33 collection(db, collectionName)
34 )
35
36 // Get a sample document for spot-checking
37 const sampleQuery = query(
38 collection(db, collectionName),
39 orderBy('__name__'),
40 limit(1)
41 )
42 const sampleSnapshot = await getDocs(sampleQuery)
43 const sampleDoc = sampleSnapshot.empty
44 ? null
45 : { id: sampleSnapshot.docs[0].id, ...sampleSnapshot.docs[0].data() }
46
47 return {
48 collection: collectionName,
49 count: countResult.data().count,
50 sampleDoc
51 }
52}
53
54async function verifyFullRestore(
55 collections: string[]
56): Promise<RestoreVerification[]> {
57 const results = await Promise.all(
58 collections.map((name) => verifyCollectionRestore(name))
59 )
60
61 for (const result of results) {
62 console.log(
63 `${result.collection}: ${result.count} documents`,
64 result.sampleDoc ? '(sample verified)' : '(empty)'
65 )
66 }
67
68 return results
69}
70
71// Usage: verify key collections after restore
72verifyFullRestore(['users', 'orders', 'products', 'settings'])

Common mistakes when restoring Firestore from a Backup

Why it's a problem: Expecting import to delete documents not present in the backup — import only overwrites matching documents

How to avoid: If you need a clean restore, delete the collection first using the Firebase CLI (firebase firestore:delete --all-collections) before importing. Be extremely careful with this approach in production.

Why it's a problem: Trying to import from a backup created with --collection-ids and expecting collections not in the export to be available

How to avoid: You can only restore collections that were included in the original export. Use full-database exports for complete backup coverage.

Why it's a problem: Not having the correct IAM roles, causing 'permission denied' during import

How to avoid: The account running the import needs Cloud Datastore Import Export Admin and Storage Object Viewer roles. Assign these in the Google Cloud Console under IAM.

Why it's a problem: Assuming PITR is available without having enabled it before the incident

How to avoid: PITR must be enabled before data loss occurs. Enable it proactively: gcloud firestore databases update --database="(default)" --enable-pitr. PITR retains data for 7 days.

Best practices

  • Schedule automated daily backups with Cloud Scheduler so you always have a recent export to restore from
  • Test your restore process periodically by importing into a separate Firebase project to verify backups are valid
  • Enable PITR on production databases as an additional safety net for data loss within the last 7 days
  • Use selective collection restores when possible to minimize the impact on unaffected data
  • Verify restored data by checking document counts and spot-checking key documents immediately after import
  • Keep backup bucket retention policies to maintain at least 30 days of daily backups
  • Document your restore procedure in a runbook so the team can execute it quickly during an incident

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I accidentally deleted a Firestore collection in my Firebase project. I have a gcloud export backup in a Cloud Storage bucket from yesterday. Walk me through the complete restore process using gcloud firestore import, including how to restore just the deleted collection and how to verify the data was restored correctly.

Firebase Prompt

Write a Firebase Cloud Function that runs a daily automated Firestore backup to Cloud Storage using the Admin SDK and gcloud, with retention of 30 days. Include a verification step that checks the export metadata. Also show the gcloud commands needed to restore from any of these backups.

Frequently asked questions

Does a Firestore import overwrite existing documents?

Yes, for documents that exist in both the backup and the live database, the import overwrites the live version with the backup version. Documents that exist only in the live database are not affected — they remain as-is. Import does not delete anything.

How long does a Firestore restore take?

Restore time depends on the size of the backup. Small databases (under 1 GB) typically restore in a few minutes. Large databases (10+ GB) can take 30 minutes to several hours. The operation runs on Google's servers and does not require your machine to stay connected.

Can I restore to a different Firebase project?

Yes. As long as the target project has access to the Cloud Storage bucket containing the export, you can run gcloud firestore import from any project. Grant the target project's service account Storage Object Viewer access on the bucket.

Is Point-in-Time Recovery available on the Spark free plan?

No. PITR is only available on the Blaze pay-as-you-go plan. It must be enabled before data loss occurs and provides a 7-day recovery window. There is an additional storage cost for PITR data retention.

Can I restore subcollections from a backup?

Yes. If the export was a full database export, all subcollections are included. If you used --collection-ids during export, only top-level collections with those IDs are included — their subcollections are included automatically, but subcollections of other collections are not.

Can RapidDev help set up automated Firestore backup and restore procedures?

Yes. RapidDev can configure automated daily backups, retention policies, restore runbooks, and PITR for your Firebase project so your data is always recoverable.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.