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

How to Update Data in Firebase Realtime Database

To update data in Firebase Realtime Database, use the update() method on a database reference to merge new values into an existing node without overwriting sibling keys. For multi-path updates, pass an object with forward-slash paths to atomically update values at different locations in a single operation. This fan-out pattern is essential for denormalized data models where the same value lives in multiple places.

What you'll learn

  • How to use update() for partial merges vs set() for full overwrites
  • How to perform multi-path (fan-out) updates across different database locations
  • How to use serverTimestamp and increment for atomic server-side operations
  • How to write Realtime Database security rules for update operations
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read10-15 minFirebase JS SDK v9+, Realtime Database on all Firebase plansMarch 2026RapidDev Engineering Team
TL;DR

To update data in Firebase Realtime Database, use the update() method on a database reference to merge new values into an existing node without overwriting sibling keys. For multi-path updates, pass an object with forward-slash paths to atomically update values at different locations in a single operation. This fan-out pattern is essential for denormalized data models where the same value lives in multiple places.

Updating Data in Firebase Realtime Database

Firebase Realtime Database stores data as a single JSON tree. Updating data correctly means choosing between set() which replaces the entire node and update() which merges only the specified keys. This tutorial covers partial updates, multi-path atomic updates (the fan-out pattern), server-side values like serverTimestamp and increment, and security rules that validate updates. These patterns are critical for keeping denormalized data consistent across your JSON tree.

Prerequisites

  • A Firebase project with Realtime Database enabled
  • Firebase JS SDK v9+ installed in your project
  • Basic understanding of the Realtime Database JSON tree structure
  • Data already written to the database (see the write data tutorial)

Step-by-step guide

1

Perform a partial update with update()

The update() function merges the provided key-value pairs into the existing data at a reference path. Keys not included in the update object are left unchanged. This is different from set(), which replaces the entire node and deletes any keys not in the new data. Import update and ref from firebase/database.

typescript
1import { ref, update } from 'firebase/database';
2import { db } from './firebase';
3
4// Only updates displayName and email — other fields are preserved
5async function updateUserProfile(userId: string) {
6 await update(ref(db, `users/${userId}`), {
7 displayName: 'Jane Doe',
8 email: 'jane@example.com',
9 updatedAt: Date.now(),
10 });
11}

Expected result: The displayName, email, and updatedAt fields are updated while all other fields on the user node remain unchanged.

2

Use multi-path updates for the fan-out pattern

Multi-path updates let you atomically write to multiple locations in the database with a single operation. This is the fan-out pattern — when you need to update the same data in several places (like updating a user's name in their profile and in every post they authored). Pass an object where keys are forward-slash-separated paths from the root.

typescript
1import { ref, update } from 'firebase/database';
2
3async function updatePostAndTimeline(
4 postId: string,
5 authorId: string,
6 newTitle: string
7) {
8 const updates: Record<string, any> = {};
9
10 // Update the post itself
11 updates[`posts/${postId}/title`] = newTitle;
12 updates[`posts/${postId}/updatedAt`] = Date.now();
13
14 // Update the post title in the author's timeline
15 updates[`user-posts/${authorId}/${postId}/title`] = newTitle;
16
17 // Update the post title in the global feed
18 updates[`feed/${postId}/title`] = newTitle;
19
20 // All three paths update atomically
21 await update(ref(db), updates);
22}

Expected result: The post title is updated in all three locations (posts, user-posts, feed) in a single atomic operation.

3

Use serverTimestamp and increment for server-side values

Server-side values ensure consistency when multiple clients write simultaneously. serverTimestamp() writes the server's current time (not the client's clock), and increment() atomically adds to a number value without reading it first. Import these from firebase/database.

typescript
1import { ref, update, serverTimestamp, increment } from 'firebase/database';
2
3async function recordPageView(pageId: string) {
4 await update(ref(db, `pages/${pageId}`), {
5 viewCount: increment(1),
6 lastViewedAt: serverTimestamp(),
7 });
8}
9
10async function decrementStock(productId: string, quantity: number) {
11 await update(ref(db, `products/${productId}`), {
12 stock: increment(-quantity),
13 updatedAt: serverTimestamp(),
14 });
15}

Expected result: The viewCount field is atomically incremented by 1 and lastViewedAt is set to the server's current timestamp.

4

Delete specific keys during an update

To remove specific keys while updating others in the same operation, set the unwanted keys to null. In Realtime Database, writing null to a path deletes that path. This works in both regular updates and multi-path updates.

typescript
1import { ref, update } from 'firebase/database';
2
3async function cleanUpUserProfile(userId: string) {
4 await update(ref(db, `users/${userId}`), {
5 // Update these fields
6 displayName: 'Updated Name',
7 updatedAt: Date.now(),
8 // Delete these fields
9 legacyField: null,
10 tempData: null,
11 });
12}

Expected result: The displayName and updatedAt fields are updated, while legacyField and tempData are completely removed from the node.

5

Write security rules for update operations

Realtime Database security rules use a JSON structure with .read, .write, and .validate rules. To restrict updates to the document owner, check auth.uid against the path. Use .validate rules to enforce data types and required fields on writes.

typescript
1// database.rules.json
2{
3 "rules": {
4 "users": {
5 "$userId": {
6 ".read": "auth != null && auth.uid === $userId",
7 ".write": "auth != null && auth.uid === $userId",
8 "displayName": {
9 ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length <= 50"
10 },
11 "email": {
12 ".validate": "newData.isString() && newData.val().matches(/^[^@]+@[^@]+$/)"
13 },
14 "role": {
15 ".write": false
16 }
17 }
18 }
19 }
20}

Expected result: Users can only update their own profiles, displayName and email are validated, and the role field cannot be modified from the client.

Complete working example

rtdb-update.ts
1import {
2 ref,
3 update,
4 set,
5 serverTimestamp,
6 increment,
7} from 'firebase/database';
8import { db } from './firebase';
9
10// Partial update — merges keys into existing data
11export async function updateFields(
12 path: string,
13 data: Record<string, any>
14): Promise<void> {
15 await update(ref(db, path), {
16 ...data,
17 updatedAt: serverTimestamp(),
18 });
19}
20
21// Full overwrite — replaces the entire node
22export async function overwriteNode(
23 path: string,
24 data: Record<string, any>
25): Promise<void> {
26 await set(ref(db, path), {
27 ...data,
28 updatedAt: serverTimestamp(),
29 });
30}
31
32// Multi-path atomic update (fan-out pattern)
33export async function fanOutUpdate(
34 updates: Record<string, any>
35): Promise<void> {
36 await update(ref(db), updates);
37}
38
39// Atomic counter increment
40export async function incrementField(
41 path: string,
42 field: string,
43 amount: number = 1
44): Promise<void> {
45 await update(ref(db, path), {
46 [field]: increment(amount),
47 updatedAt: serverTimestamp(),
48 });
49}
50
51// Example: update post title across multiple locations
52export async function updatePostTitle(
53 postId: string,
54 authorId: string,
55 newTitle: string
56): Promise<void> {
57 const updates: Record<string, any> = {
58 [`posts/${postId}/title`]: newTitle,
59 [`posts/${postId}/updatedAt`]: serverTimestamp(),
60 [`user-posts/${authorId}/${postId}/title`]: newTitle,
61 [`feed/${postId}/title`]: newTitle,
62 };
63 await fanOutUpdate(updates);
64}

Common mistakes when updating Data in Firebase Realtime Database

Why it's a problem: Using set() instead of update() and accidentally overwriting the entire node including unspecified fields

How to avoid: Use update() for partial merges. Only use set() when you intentionally want to replace the entire node with new data.

Why it's a problem: Expecting update() to deep-merge nested objects when it only does a shallow merge

How to avoid: Use forward-slash paths for nested fields: { 'address/city': 'NYC' } instead of { address: { city: 'NYC' } } to avoid overwriting sibling keys.

Why it's a problem: Not using multi-path updates for denormalized data, leading to inconsistent copies

How to avoid: When the same data lives in multiple paths, always use a single multi-path update to change all copies atomically.

Best practices

  • Use update() for partial modifications and set() only when you want to replace the entire node
  • Use multi-path updates (fan-out) to keep denormalized data consistent across the JSON tree
  • Always include a serverTimestamp() field like updatedAt to track when nodes were last modified
  • Use increment() for counters instead of reading, modifying, and writing — it avoids race conditions
  • Write .validate rules to enforce data types and value ranges on every writable field
  • Set specific child paths to .write: false to make fields read-only even when the parent is writable
  • Delete fields by setting them to null within an update operation instead of using remove() separately

Still stuck?

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

ChatGPT Prompt

Show me how to update data in Firebase Realtime Database using the v9 modular SDK. Include update() for partial merges, multi-path fan-out updates, serverTimestamp, increment, deleting keys by setting null, and security rules for validating updates.

Firebase Prompt

Write TypeScript utility functions for Firebase Realtime Database updates: partial update with update(), full overwrite with set(), multi-path fan-out pattern, atomic increment and serverTimestamp. Use Firebase modular SDK v9+ imports from 'firebase/database'.

Frequently asked questions

What is the difference between update() and set() in Realtime Database?

update() merges the specified keys into the existing node without touching other keys. set() replaces the entire node with the new data, deleting any keys not in the new object. Use update() for partial modifications and set() for full overwrites.

Are multi-path updates atomic?

Yes. A multi-path update either writes all paths successfully or writes none. If any path fails a security rule check, the entire operation is rejected.

Can I update data while the device is offline?

Yes. With persistence enabled (default on mobile), updates are stored locally and synced when the device reconnects. Local listeners see the update immediately.

How do I update a deeply nested field without overwriting siblings?

Use forward-slash paths in the update object: update(ref(db, 'users/uid'), { 'settings/notifications/email': true }). This updates only the email key without affecting other notification settings.

Is there a limit on how many paths I can update at once?

There is no documented hard limit on the number of paths in a multi-path update, but the total payload size must be under 16 MB. In practice, keep multi-path updates to a few hundred paths for best performance.

Can RapidDev help design my Realtime Database schema and update patterns?

Yes. RapidDev can help you design efficient denormalized JSON structures, implement fan-out update patterns, write security rules, and optimize for real-time performance.

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.