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

How to Delete a Document in Firestore

To delete a document in Firestore, use deleteDoc() with a document reference from the modular SDK v9+. Pass the result of doc(db, 'collection', 'documentId') to deleteDoc(). Deleting a document does not delete its subcollections — you must delete subcollection documents separately using a recursive approach or a Cloud Function. Always write security rules that grant delete permission only to authorized users.

What you'll learn

  • How to delete a single document using the modular deleteDoc function
  • How to handle subcollection cleanup when deleting parent documents
  • How to write Firestore security rules that allow delete operations
  • How to delete multiple documents in a batch operation
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate7 min read10-15 minFirebase JS SDK v9+, Firestore (all plans)March 2026RapidDev Engineering Team
TL;DR

To delete a document in Firestore, use deleteDoc() with a document reference from the modular SDK v9+. Pass the result of doc(db, 'collection', 'documentId') to deleteDoc(). Deleting a document does not delete its subcollections — you must delete subcollection documents separately using a recursive approach or a Cloud Function. Always write security rules that grant delete permission only to authorized users.

Deleting Documents in Firestore

Firestore's modular SDK provides the deleteDoc() function for removing documents from your database. This tutorial covers single document deletion, batch deletes for removing multiple documents at once, handling subcollections that survive parent document deletion, and the security rules required to authorize delete operations from your client app.

Prerequisites

  • A Firebase project with Firestore enabled
  • Firebase JS SDK v9+ installed in your project
  • Firestore initialized with initializeApp and getFirestore
  • Security rules that grant delete permission (covered in this tutorial)

Step-by-step guide

1

Delete a single document with deleteDoc

Import deleteDoc and doc from firebase/firestore. Create a document reference by passing the Firestore instance, collection name, and document ID to doc(). Then call deleteDoc() with that reference. The function returns a Promise that resolves when the delete is committed to the server. If the document does not exist, deleteDoc succeeds silently without throwing an error.

typescript
1import { getFirestore, doc, deleteDoc } from 'firebase/firestore';
2
3const db = getFirestore();
4
5// Delete a single document by ID
6async function deleteTodo(todoId: string): Promise<void> {
7 const todoRef = doc(db, 'todos', todoId);
8 await deleteDoc(todoRef);
9 console.log('Document deleted:', todoId);
10}

Expected result: The document is removed from Firestore. Subsequent reads return a snapshot where exists() is false.

2

Write security rules to allow delete operations

Firestore security rules must explicitly allow delete operations. By default, if you have allow write rules, they cover create, update, and delete. For finer control, use allow delete as a separate permission. A common pattern is to let users delete only their own documents by checking that request.auth.uid matches the document's authorId or userId field.

typescript
1rules_version = '2';
2service cloud.firestore {
3 match /databases/{database}/documents {
4 match /todos/{todoId} {
5 // Only the document owner can delete
6 allow delete: if request.auth != null
7 && request.auth.uid == resource.data.userId;
8
9 // Read and create rules
10 allow read: if request.auth != null
11 && request.auth.uid == resource.data.userId;
12 allow create: if request.auth != null
13 && request.auth.uid == request.resource.data.userId;
14 }
15 }
16}

Expected result: Authenticated users can delete documents where the userId field matches their auth UID. Unauthorized delete attempts throw a permission-denied error.

3

Delete specific fields from a document instead of the entire document

Sometimes you want to remove a field from a document rather than deleting the whole document. Use updateDoc with deleteField() as the value. This removes the specified field while keeping the rest of the document intact.

typescript
1import { doc, updateDoc, deleteField } from 'firebase/firestore';
2
3const db = getFirestore();
4
5// Remove the 'completedAt' field from a todo document
6async function removeCompletedTimestamp(todoId: string): Promise<void> {
7 const todoRef = doc(db, 'todos', todoId);
8 await updateDoc(todoRef, {
9 completedAt: deleteField()
10 });
11 console.log('Field removed from document:', todoId);
12}

Expected result: The completedAt field is removed from the document. All other fields remain unchanged.

4

Delete multiple documents in a batch

Use writeBatch to delete multiple documents atomically. All deletes in a batch either succeed together or fail together. This is useful for cleaning up related data across a collection. Batches are limited to 500 operations, so for larger deletions, split them into multiple batches.

typescript
1import { getFirestore, doc, writeBatch, collection, getDocs, query, where } from 'firebase/firestore';
2
3const db = getFirestore();
4
5// Delete all completed todos for the current user
6async function deleteCompletedTodos(userId: string): Promise<number> {
7 const q = query(
8 collection(db, 'todos'),
9 where('userId', '==', userId),
10 where('completed', '==', true)
11 );
12
13 const snapshot = await getDocs(q);
14 const batch = writeBatch(db);
15
16 snapshot.docs.forEach((docSnap) => {
17 batch.delete(docSnap.ref);
18 });
19
20 await batch.commit();
21 return snapshot.size;
22}

Expected result: All matching documents are deleted atomically. The function returns the count of deleted documents.

5

Handle subcollection cleanup

Deleting a parent document does not delete its subcollections. Subcollection documents continue to exist as orphaned data. To fully clean up, you must delete subcollection documents explicitly. From the client side, query the subcollection and delete each document. For production apps, use a Cloud Function triggered on document deletion to handle recursive cleanup server-side with the Admin SDK.

typescript
1import { collection, getDocs, writeBatch, doc } from 'firebase/firestore';
2
3const db = getFirestore();
4
5// Delete a document and its subcollection (client-side)
6async function deleteProjectWithTasks(projectId: string): Promise<void> {
7 // First delete all subcollection documents
8 const tasksRef = collection(db, 'projects', projectId, 'tasks');
9 const tasksSnapshot = await getDocs(tasksRef);
10
11 const batch = writeBatch(db);
12 tasksSnapshot.docs.forEach((taskDoc) => {
13 batch.delete(taskDoc.ref);
14 });
15
16 // Then delete the parent document
17 batch.delete(doc(db, 'projects', projectId));
18 await batch.commit();
19}

Expected result: Both the parent document and all its subcollection documents are deleted in a single atomic batch operation.

Complete working example

firestore-delete.ts
1import { initializeApp } from 'firebase/app';
2import {
3 getFirestore,
4 doc,
5 deleteDoc,
6 updateDoc,
7 deleteField,
8 writeBatch,
9 collection,
10 getDocs,
11 query,
12 where
13} from 'firebase/firestore';
14
15const app = initializeApp({
16 // Your Firebase config
17});
18const db = getFirestore(app);
19
20// Delete a single document
21export async function deleteTodo(todoId: string): Promise<void> {
22 const todoRef = doc(db, 'todos', todoId);
23 await deleteDoc(todoRef);
24}
25
26// Remove a field from a document
27export async function removeField(
28 todoId: string,
29 fieldName: string
30): Promise<void> {
31 const todoRef = doc(db, 'todos', todoId);
32 await updateDoc(todoRef, { [fieldName]: deleteField() });
33}
34
35// Batch delete all completed todos for a user
36export async function deleteCompletedTodos(
37 userId: string
38): Promise<number> {
39 const q = query(
40 collection(db, 'todos'),
41 where('userId', '==', userId),
42 where('completed', '==', true)
43 );
44 const snapshot = await getDocs(q);
45
46 if (snapshot.empty) return 0;
47
48 const batch = writeBatch(db);
49 snapshot.docs.forEach((d) => batch.delete(d.ref));
50 await batch.commit();
51 return snapshot.size;
52}
53
54// Delete parent document and its subcollection
55export async function deleteWithSubcollection(
56 parentCollection: string,
57 parentId: string,
58 subCollection: string
59): Promise<void> {
60 const subRef = collection(db, parentCollection, parentId, subCollection);
61 const subSnapshot = await getDocs(subRef);
62
63 const batch = writeBatch(db);
64 subSnapshot.docs.forEach((d) => batch.delete(d.ref));
65 batch.delete(doc(db, parentCollection, parentId));
66 await batch.commit();
67}

Common mistakes when deleting a Document in Firestore

Why it's a problem: Assuming deleteDoc also deletes subcollections

How to avoid: Subcollections survive parent document deletion. You must query and delete subcollection documents separately, either from the client or via a Cloud Function using the Admin SDK's recursiveDelete method.

Why it's a problem: Not adding a specific 'allow delete' rule in security rules

How to avoid: If you only have 'allow create' and 'allow update' rules, delete operations will be denied. Add 'allow delete: if ...' as a separate permission, or use the broader 'allow write' which covers create, update, and delete.

Why it's a problem: Trying to delete more than 500 documents in a single batch

How to avoid: Firestore batches are limited to 500 operations. For larger deletions, split documents into groups of 500 and commit each batch sequentially.

Best practices

  • Always verify user authorization in security rules before allowing deletes — check request.auth.uid against the document owner
  • Use writeBatch for deleting multiple documents to ensure atomicity
  • Implement server-side cleanup with Cloud Functions for subcollection data when deleting parent documents
  • Consider soft deletes (adding a deletedAt timestamp) instead of hard deletes when you need audit trails
  • Limit batch sizes to 500 operations and process larger deletions in sequential batches
  • Test delete security rules in the Emulator Suite before deploying to production
  • Log delete operations with structured data for debugging and audit purposes

Still stuck?

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

ChatGPT Prompt

Show me how to delete a document in Firestore using the modular SDK v9+. Include examples for single delete, batch delete of multiple documents, handling subcollection cleanup, and the Firestore security rules needed to allow delete operations for document owners only.

Firebase Prompt

Write Firestore delete utility functions using the modular SDK v9+: single document deletion with deleteDoc, batch deletion of multiple documents matching a query, subcollection cleanup before parent deletion, and field removal with deleteField. Include security rules for owner-only delete permission.

Frequently asked questions

Does deleting a document delete its subcollections?

No. Deleting a parent document leaves its subcollections intact as orphaned data. You must delete subcollection documents separately, either from client code or using a Cloud Function with the Admin SDK's recursiveDelete method.

Does deleteDoc throw an error if the document does not exist?

No. deleteDoc succeeds silently even if the document does not exist. If you need to verify the document existed, read it with getDoc before deleting.

How do I delete all documents in a collection?

There is no single API call to delete an entire collection. Query all documents with getDocs, then delete them in batches of 500 using writeBatch. For large collections, use the Firebase CLI command firebase firestore:delete --all-collections or the Admin SDK's recursiveDelete.

Can I undo a Firestore document deletion?

No. Firestore deletions are permanent and cannot be undone through the API. Enable point-in-time recovery (PITR) on your database for disaster recovery, or implement soft deletes by adding a deletedAt field instead of actually removing documents.

What is the difference between deleteDoc and deleteField?

deleteDoc removes an entire document from the collection. deleteField is used inside updateDoc to remove a specific field from a document while keeping all other fields intact.

Can RapidDev help with complex Firestore data cleanup workflows?

Yes, RapidDev can build Cloud Functions for recursive subcollection deletion, implement soft-delete patterns with scheduled cleanup, and design security rules that safely authorize delete operations for your application.

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.