Saving Data with Firebase Realtime Database for C++ Stay organized with collections Save and categorize content based on your preferences.
Get Started
See theGet Started guide first if you have notyet set up your app and access to the database.
Get a DatabaseReference
To write data to the Database, you need an instance ofDatabaseReference:
// Get the root reference location of the database.firebase::database::DatabaseReferencedbref=database->GetReference();
Saving Data
There are four methods for writing data to theFirebase Realtime Database:
| Method | Common uses |
|---|---|
SetValue() | Write or replace data to a defined path, such asusers/<user-id>/<username>. |
PushChild() | Add to a list of data. Every time you callPush(), Firebase generates a unique key that can also be used as a unique identifier, such asuser-scores/<user-id>/<unique-score-id>. |
UpdateChildren() | Update some of the keys for a defined path without replacing all of the data. |
RunTransaction() | Update complex data that could be corrupted by concurrent updates. |
Write, update, or delete data at a reference
Basic write operations
For basic write operations, you can useSetValue() to save data to aspecified reference, replacing any existing data at that path. You can use thismethod to pass types accepted by JSON through a Variant type which supports:
- Null (this deletes the data)
- Integers (64-bit)
- Double precision floating point numbers
- Booleans
- Strings
- Vectors of Variants
- Maps of strings to Variants
UsingSetValue() in this way overwrites data at the specified location,including any child nodes. However, you can still update a child withoutrewriting the entire object. If you want to allow users to update their profilesyou could update the username as follows:
dbref.Child("users").Child(userId).Child("username").SetValue(name);Append to a list of data
Use thePushChild() method to append data to a list in multiuser applications.ThePushChild() method generates a unique key every time a newchild is added to the specified Firebase reference. By using theseauto-generated keys for each new element in the list, several clients canadd children to the same location at the same time without write conflicts. Theunique key generated byPushChild() is based on a timestamp, so list items areautomatically ordered chronologically.
You can use the reference to the new data returned by thePushChild() methodto get the value of the child's auto-generated key or set data for the child.CallingGetKey() on aPushChild() reference returns the value of theauto-generated key.
Update specific fields
To simultaneously write to specific children of a node without overwriting otherchild nodes, use theUpdateChildren() method.
When callingUpdateChildren(), you can update lower-level child values byspecifying a path for the key. If data is stored in multiple locations to scalebetter, you can update all instances of that data usingdata fan-out. For example, agame might have aLeaderboardEntry class like this:
classLeaderboardEntry{std::stringuid;intscore=0;public:LeaderboardEntry(){}LeaderboardEntry(std::stringuid,intscore){this->uid=uid;this->score=score;}std::map<std::string,Object>ToMap(){std::map<string,Variant>result=newstd::map<string,Variant>();result["uid"]=Variant(uid);result["score"]=Variant(score);returnresult;}}
To create aLeaderboardEntry and simultaneously update it to the recent scorefeed and the user's own score list, the game uses the following code:
voidWriteNewScore(std::stringuserId,intscore){// Create new entry at /user-scores/$userid/$scoreid and at// /leaderboard/$scoreid simultaneouslystd::stringkey=dbref.Child("scores").PushChild().GetKey();LeaderBoardEntryentry=newLeaderBoardEntry(userId,score);std::map<std::string,Variant>entryValues=entry.ToMap();std::map<string,Variant>childUpdates=newstd::map<string,Variant>();childUpdates["/scores/"+key]=entryValues;childUpdates["/user-scores/"+userId+"/"+key]=entryValues;dbref.UpdateChildren(childUpdates);}
This example usesPushChild() to create an entry in the node containingentries for all users at/scores/$key and simultaneously retrieve the key withkey(). The key can then be used to create a second entry in the user'sscores at/user-scores/$userid/$key.
Using these paths, you can perform simultaneous updates to multiple locations inthe JSON tree with a single call toUpdateChildren(), such as how thisexample creates the new entry in both locations. Simultaneous updates made thisway are atomic: either all updates succeed or all updates fail.
Delete data
The simplest way to delete data is to callRemoveValue() on a reference to thelocation of that data.
You can also delete by specifying anullVariant as the value for another writeoperation such asSetValue() orUpdateChildren(). You can use thistechnique withUpdateChildren() to delete multiple children in a single APIcall.
Know when your data is committed.
To know when your data is committed to theFirebase Realtime Database server, checktheFuture result for success.
Save data as transactions
When working with data that could be corrupted by concurrentmodifications, such as incremental counters, you can use atransaction operation.You give this operation aDoTransaction function. This update function takesthe current state of the data as an argument and returns the new desired stateyou would like to write. If another client writes to the location before yournew value is successfully written, your update function is called again with thenew current value, and the write is retried.
For instance, in a game you could allow users to update a leaderboard withthe five highest scores:
voidAddScoreToLeaders(std::stringemail,longscore,DatabaseReferenceleaderBoardRef){leaderBoardRef.RunTransaction([](firebase::database::MutableData*mutableData){if(mutableData.children_count()>=MaxScores){longminScore=LONG_MAX;MutableData*minVal=null;std::vector<MutableData>children=mutableData.children();std::vector<MutableData>::iteratorit;for(it=children.begin();it!=children.end();++it){if(!it->value().is_map())continue;longchildScore=(long)it->Child("score").value().int64_value();if(childScore<minScore){minScore=childScore;minVal=&*it;}}if(minScore>score){// The new score is lower than the existing 5 scores, abort.returnkTransactionResultAbort;}// Remove the lowest score.children.Remove(minVal);}// Add the new high score.std::map<std::string,Variant>newScoreMap=newstd::map<std::string,Variant>();newScoreMap["score"]=score;newScoreMap["email"]=email;children.Add(newScoreMap);mutableData->set_value(children);returnkTransactionResultSuccess;});}
Using a transaction prevents the leaderboard from being incorrect if multipleusers record scores at the same time or the client had stale data. If thetransaction is rejected, the server returns the current value to the client,which runs the transaction again with the updated value. This repeats until thetransaction is accepted or too many attempts have been made.
Note: BecauseRunTransaction() is called multiple times, it must be able tohandlenull data. Even if there is existing data in your remote database,it may not be locally cached when the transaction function is run, resultinginnull for the initial value.Write data offline
If a client loses its network connection, your app will continue functioningcorrectly.
Every client connected to a Firebase database maintains its own internal versionof any active data. When data is written, it's written to this local versionfirst. The Firebase client then synchronizes that data with the remote databaseservers and with other clients on a "best-effort" basis.
As a result, all writes to the database trigger local events immediately, beforeany data is written to the server. This means your app remainsresponsive regardless of network latency or connectivity.
Once connectivity is reestablished, your app receives the appropriate set ofevents so that the client syncs with the current server state, without having towrite any custom code.
Next Steps
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-17 UTC.