# How to Restore Firestore from a Backup

- Tool: Firebase
- Difficulty: Intermediate
- Time required: 15-20 min
- Compatibility: Firebase Blaze plan, gcloud CLI, Firestore (Native mode)
- Last updated: March 2026

## 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.

## Before you start

- 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.

```
# List all exports in your backup bucket
gcloud storage ls gs://your-backup-bucket/

# List contents of a specific export folder
gcloud storage ls gs://your-backup-bucket/2026-03-28-daily-backup/

# You should see an overall_export_metadata file
# gs://your-backup-bucket/2026-03-28-daily-backup/overall_export_metadata
# 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.

```
# Import the full backup
gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup

# The command outputs an operation ID like:
# operation: projects/your-project/databases/(default)/operations/abc123

# Check import progress
gcloud 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.

```
# Restore only the 'users' and 'orders' collections
gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup \
  --collection-ids=users,orders

# Restore a single collection
gcloud firestore import gs://your-backup-bucket/2026-03-28-daily-backup \
  --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.

```
# Check if PITR is enabled on your database
gcloud firestore databases describe --database="(default)"

# Enable PITR (must be done BEFORE data loss occurs)
gcloud firestore databases update --database="(default)" \
  --enable-pitr

# Restore to a point in time (creates a new database)
# Use ISO 8601 timestamp format
gcloud firestore databases restore \
  --source-database="(default)" \
  --destination-database="restored-db" \
  --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.

```
import { initializeApp } from 'firebase/app'
import { getFirestore, collection, getCountFromServer, doc, getDoc } from 'firebase/firestore'

const app = initializeApp({ /* your config */ })
const db = getFirestore(app)

async function verifyRestore() {
  // Check document counts
  const usersCount = await getCountFromServer(collection(db, 'users'))
  console.log('Users collection count:', usersCount.data().count)

  const ordersCount = await getCountFromServer(collection(db, 'orders'))
  console.log('Orders collection count:', ordersCount.data().count)

  // Spot-check a specific document
  const testDoc = await getDoc(doc(db, 'users', 'known-user-id'))
  if (testDoc.exists()) {
    console.log('Test user data:', testDoc.data())
  } else {
    console.warn('Test user document not found — restore may be incomplete.')
  }
}
```

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

## Complete code example

File: `restore-verification.ts`

```typescript
import { initializeApp } from 'firebase/app'
import {
  getFirestore,
  collection,
  getCountFromServer,
  doc,
  getDoc,
  getDocs,
  query,
  limit,
  orderBy
} from 'firebase/firestore'

const app = initializeApp({
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN!,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!
})

const db = getFirestore(app)

interface RestoreVerification {
  collection: string
  count: number
  sampleDoc: Record<string, any> | null
}

async function verifyCollectionRestore(
  collectionName: string
): Promise<RestoreVerification> {
  // Get total document count
  const countResult = await getCountFromServer(
    collection(db, collectionName)
  )

  // Get a sample document for spot-checking
  const sampleQuery = query(
    collection(db, collectionName),
    orderBy('__name__'),
    limit(1)
  )
  const sampleSnapshot = await getDocs(sampleQuery)
  const sampleDoc = sampleSnapshot.empty
    ? null
    : { id: sampleSnapshot.docs[0].id, ...sampleSnapshot.docs[0].data() }

  return {
    collection: collectionName,
    count: countResult.data().count,
    sampleDoc
  }
}

async function verifyFullRestore(
  collections: string[]
): Promise<RestoreVerification[]> {
  const results = await Promise.all(
    collections.map((name) => verifyCollectionRestore(name))
  )

  for (const result of results) {
    console.log(
      `${result.collection}: ${result.count} documents`,
      result.sampleDoc ? '(sample verified)' : '(empty)'
    )
  }

  return results
}

// Usage: verify key collections after restore
verifyFullRestore(['users', 'orders', 'products', 'settings'])
```

## Common mistakes

- **Expecting import to delete documents not present in the backup — import only overwrites matching documents** — undefined Fix: 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.
- **Trying to import from a backup created with --collection-ids and expecting collections not in the export to be available** — undefined Fix: You can only restore collections that were included in the original export. Use full-database exports for complete backup coverage.
- **Not having the correct IAM roles, causing 'permission denied' during import** — undefined Fix: 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.
- **Assuming PITR is available without having enabled it before the incident** — undefined Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/firebase-tutorial/how-to-restore-firestore-from-backup
© RapidDev — https://www.rapidevelopers.com/firebase-tutorial/how-to-restore-firestore-from-backup
