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

How to Backup Firestore Data with Exports and PITR

Back up Firestore data using the gcloud firestore export command, which writes data to a Google Cloud Storage bucket. For automated backups, schedule exports with Cloud Scheduler and a Cloud Function. The Blaze plan is required for both gcloud exports and scheduled functions. Pro tip: point-in-time recovery (PITR) is available for Firestore databases, letting you restore to any moment within the last 7 days. Always test your restore process before you need it.

What you'll learn

  • How to export Firestore data to a Cloud Storage bucket using gcloud CLI
  • How to schedule automated daily backups with Cloud Scheduler and Cloud Functions
  • How to use point-in-time recovery (PITR) for Firestore
  • How to selectively export specific collections
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, Cloud SchedulerMarch 2026RapidDev Engineering Team
TL;DR

Back up Firestore data using the gcloud firestore export command, which writes data to a Google Cloud Storage bucket. For automated backups, schedule exports with Cloud Scheduler and a Cloud Function. The Blaze plan is required for both gcloud exports and scheduled functions. Pro tip: point-in-time recovery (PITR) is available for Firestore databases, letting you restore to any moment within the last 7 days. Always test your restore process before you need it.

Backing Up Firestore Data with Exports, Scheduling, and PITR

Firestore does not have a one-click backup button — you must use Google Cloud's managed export/import service. This tutorial covers three backup strategies: manual exports with gcloud CLI, automated scheduled exports with Cloud Scheduler, and point-in-time recovery for instant rollbacks. All backup methods require the Blaze plan and a Cloud Storage bucket. You will also learn how to export specific collections and verify your backups by testing imports.

Prerequisites

  • A Firebase project on the Blaze plan with Firestore data to back up
  • Google Cloud CLI (gcloud) installed and authenticated
  • A Google Cloud Storage bucket for storing exports (or you will create one)
  • Firebase CLI installed for deploying scheduled functions

Step-by-step guide

1

Create a Cloud Storage bucket for backups

Firestore exports are stored in Google Cloud Storage (GCS) buckets. Create a dedicated bucket in the same region as your Firestore database to avoid cross-region transfer costs. Use a naming convention that makes the bucket easy to identify.

typescript
1# Create a bucket in the same region as your Firestore database
2gcloud storage buckets create gs://your-project-id-firestore-backups \
3 --location=us-central1 \
4 --uniform-bucket-level-access
5
6# Verify the bucket was created
7gcloud storage buckets list | grep firestore-backups

Expected result: A new Cloud Storage bucket exists for storing your Firestore backups.

2

Run a manual Firestore export

Use the gcloud firestore export command to create a full backup of your Firestore database. The export runs as a long-running operation on Google's infrastructure — it does not block your application or affect database performance. The exported data is stored in the specified GCS bucket.

typescript
1# Full database export
2gcloud firestore export gs://your-project-id-firestore-backups/$(date +%Y-%m-%d) \
3 --project=your-project-id
4
5# Export specific collections only
6gcloud firestore export gs://your-project-id-firestore-backups/$(date +%Y-%m-%d)-users \
7 --collection-ids=users,orders \
8 --project=your-project-id
9
10# Check export status
11gcloud firestore operations list --project=your-project-id

Expected result: Export files appear in your Cloud Storage bucket under the date-stamped folder.

3

Schedule automated daily backups

Create a Cloud Function triggered by Cloud Scheduler to run Firestore exports automatically. The function uses the Firestore Admin API to start an export operation. Schedule it to run daily at a low-traffic time.

typescript
1import { onSchedule } from "firebase-functions/v2/scheduler";
2import { logger } from "firebase-functions";
3import * as admin from "firebase-admin";
4
5admin.initializeApp();
6
7const BUCKET = "gs://your-project-id-firestore-backups";
8const PROJECT = "your-project-id";
9
10export const scheduledFirestoreBackup = onSchedule(
11 {
12 schedule: "every day 02:00",
13 timeZone: "America/New_York",
14 retryCount: 3,
15 },
16 async () => {
17 const date = new Date().toISOString().split("T")[0];
18 const outputUri = `${BUCKET}/${date}`;
19
20 try {
21 const client = new admin.firestore.v1.FirestoreAdminClient();
22 const [operation] = await client.exportDocuments({
23 name: `projects/${PROJECT}/databases/(default)`,
24 outputUriPrefix: outputUri,
25 });
26
27 logger.info(`Backup started: ${outputUri}`, {
28 operationName: operation.name,
29 });
30 } catch (error) {
31 logger.error("Backup failed:", error);
32 throw error; // Triggers retry
33 }
34 }
35);

Expected result: A Cloud Function runs daily at 2 AM and exports Firestore data to the backup bucket.

4

Enable point-in-time recovery (PITR)

PITR lets you restore your Firestore database to any second within the last 7 days. Enable it in the Google Cloud Console under Firestore > Settings. PITR uses continuous backups and is more granular than scheduled exports, but it costs extra based on storage used.

typescript
1# Enable PITR via gcloud
2gcloud firestore databases update --type=firestore-native \
3 --enable-pitr \
4 --project=your-project-id
5
6# Restore to a specific point in time (ISO 8601 format)
7# This creates a new database it does not overwrite the existing one
8gcloud firestore databases restore \
9 --source-database=(default) \
10 --destination-database=restored-db \
11 --snapshot-time=2026-03-27T15:30:00Z \
12 --project=your-project-id

Expected result: PITR is enabled, and you can restore to any second within the last 7 days.

5

Test your backup by importing into a test project

A backup is only useful if you can restore it. Test your exports by importing into a separate Firebase project or the same project's test database. Use gcloud firestore import with the export path.

typescript
1# Import into the same project (overwrites matching documents)
2gcloud firestore import gs://your-project-id-firestore-backups/2026-03-27 \
3 --project=your-project-id
4
5# Import specific collections only
6gcloud firestore import gs://your-project-id-firestore-backups/2026-03-27 \
7 --collection-ids=users \
8 --project=your-project-id
9
10# Import into a different (test) project
11gcloud firestore import gs://your-project-id-firestore-backups/2026-03-27 \
12 --project=your-test-project-id

Expected result: Backup data is successfully imported and you have verified the restore process works.

Complete working example

functions/src/scheduled-backup.ts
1import { onSchedule } from "firebase-functions/v2/scheduler";
2import { logger } from "firebase-functions";
3import * as admin from "firebase-admin";
4
5admin.initializeApp();
6
7const BUCKET = "gs://your-project-id-firestore-backups";
8const PROJECT_ID = process.env.GCLOUD_PROJECT || "your-project-id";
9
10// Runs daily at 2 AM Eastern — exports full Firestore database
11export const scheduledFirestoreBackup = onSchedule(
12 {
13 schedule: "every day 02:00",
14 timeZone: "America/New_York",
15 retryCount: 3,
16 maxInstances: 1,
17 },
18 async () => {
19 const date = new Date().toISOString().split("T")[0];
20 const outputUri = `${BUCKET}/${date}`;
21
22 const client = new admin.firestore.v1.FirestoreAdminClient();
23
24 try {
25 const [operation] = await client.exportDocuments({
26 name: `projects/${PROJECT_ID}/databases/(default)`,
27 outputUriPrefix: outputUri,
28 // Uncomment to export specific collections:
29 // collectionIds: ["users", "orders", "products"],
30 });
31
32 logger.info("Firestore backup started", {
33 outputUri,
34 operationName: operation.name,
35 timestamp: new Date().toISOString(),
36 });
37 } catch (error) {
38 logger.error("Firestore backup failed", {
39 error: String(error),
40 outputUri,
41 timestamp: new Date().toISOString(),
42 });
43 throw error;
44 }
45 }
46);
47
48// Optional: Clean up old backups (keep last 30 days)
49export const cleanupOldBackups = onSchedule(
50 {
51 schedule: "every day 03:00",
52 timeZone: "America/New_York",
53 maxInstances: 1,
54 },
55 async () => {
56 const storage = admin.storage();
57 const bucket = storage.bucket(
58 "your-project-id-firestore-backups"
59 );
60
61 const cutoffDate = new Date();
62 cutoffDate.setDate(cutoffDate.getDate() - 30);
63
64 const [files] = await bucket.getFiles();
65 let deletedCount = 0;
66
67 for (const file of files) {
68 const fileDate = new Date(file.metadata.timeCreated);
69 if (fileDate < cutoffDate) {
70 await file.delete();
71 deletedCount++;
72 }
73 }
74
75 logger.info(`Cleaned up ${deletedCount} old backup files`);
76 }
77);

Common mistakes when backing up Firestore Data with Exports and PITR

Why it's a problem: Creating the backup bucket in a different region than the Firestore database, causing slow exports and transfer costs

How to avoid: Check your Firestore database region in Firebase Console > Firestore and create the GCS bucket in the same region using --location=your-region.

Why it's a problem: Assuming Firestore exports are atomic snapshots of the entire database at one moment

How to avoid: Exports are eventually consistent — documents may be captured at slightly different points during the export. For truly consistent snapshots, use PITR.

Why it's a problem: Never testing the restore process and discovering issues only during an actual incident

How to avoid: Schedule quarterly restore tests to a separate project. Verify data integrity by comparing document counts and spot-checking key documents.

Why it's a problem: Not setting up backup rotation, causing storage costs to grow indefinitely

How to avoid: Implement a cleanup function or lifecycle policy on the GCS bucket to automatically delete backups older than 30-90 days.

Best practices

  • Create the backup GCS bucket in the same region as your Firestore database to minimize latency and cost
  • Schedule automated daily exports with Cloud Scheduler — do not rely on manual backups alone
  • Enable point-in-time recovery (PITR) for the most granular restore capability (any second in the last 7 days)
  • Test your restore process quarterly by importing into a separate project and verifying data integrity
  • Use --collection-ids to export only critical collections if full exports are too slow or expensive
  • Set up lifecycle policies or a cleanup function to delete backups older than your retention period
  • Log all backup operations with structured logging for monitoring and alerting on failures
  • Keep at least one off-site backup copy (different GCS bucket or region) for disaster recovery

Still stuck?

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

ChatGPT Prompt

Show me how to back up my Firestore database automatically using a scheduled Cloud Function in Firebase. I need it to export to a Google Cloud Storage bucket daily and clean up backups older than 30 days. Use v2 Cloud Functions syntax with onSchedule.

Firebase Prompt

Set up automated Firestore backups: create a Cloud Function using onSchedule from firebase-functions/v2/scheduler that runs daily at 2 AM, exports the full Firestore database to a GCS bucket using the FirestoreAdminClient, and logs the operation name. Include error handling and retry configuration.

Frequently asked questions

Does a Firestore export affect database performance?

No. Exports run on Google's managed infrastructure and do not consume your database's read/write quota or affect application performance. However, you are charged for the read operations performed during the export.

Can I back up Firestore on the free Spark plan?

No. Firestore managed exports and Cloud Functions (needed for scheduling) both require the Blaze plan. The only free alternative is manually downloading documents through the Firebase Console, which is impractical for large datasets.

How long does a Firestore export take?

It depends on database size. Small databases (under 10,000 documents) export in under a minute. Large databases with millions of documents can take hours. The operation runs asynchronously — you do not need to wait for it.

What is point-in-time recovery (PITR) and how is it different from exports?

PITR uses continuous replication to let you restore your database to any second within the last 7 days. Exports are periodic snapshots you schedule yourself. PITR is more granular and faster to restore but costs extra for the continuous backup storage.

Can I export specific collections instead of the entire database?

Yes. Use the --collection-ids flag with gcloud firestore export to specify which collections to include: gcloud firestore export gs://bucket/path --collection-ids=users,orders.

Does importing overwrite existing data?

Import overwrites documents with matching IDs but does not delete documents that are not in the backup. It is an additive merge, not a full replacement. For a clean restore, delete the target collection first or import into a fresh project.

How much does Firestore backup storage cost?

You pay standard Google Cloud Storage rates for the exported files (approximately $0.02-0.026 per GB per month depending on region and storage class). You also pay for the Firestore read operations during the export at standard rates.

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.