Theory
Saving data to the cloud
Now that you can point a DatabaseReference at a path, you can write data there. When a student registers for an event in FestConnect, that registration must be saved to the Realtime Database so it persists and syncs.
Writing is mostly one method, setValue, plus one important helper, push, for adding items to a list without them clobbering each other. This lesson shows both, and the crucial difference between them. Getting writes right, especially the push-versus-setValue distinction, prevents a very common data-loss bug.
Theory
setValue writes at a path
setValue(data) writes a value at the reference's path, replacing whatever was there. You can write a primitive, a map, or a simple object (a Kotlin data class).
So database.getReference("settings").child("theme").setValue("dark") stores 'dark' at settings/theme. This is perfect for a single, known location, one setting, one profile field. But be careful: because setValue overwrites, writing to the same fixed path twice replaces the first value. That is fine for single items, but wrong for a list, where you want to keep adding entries. For that you need push.
Practical
Writing a single value, and adding to a list with push
val db = FirebaseDatabase.getInstance()
// Single, known location: setValue overwrites
db.getReference("settings").child("theme").setValue("dark")
// A list: push() makes a UNIQUE key per item, so entries never collide
val eventsRef = db.getReference("events")
val event = mapOf("name" to "Robotics", "seats" to 50)
eventsRef.push().setValue(event) // events/<auto-id>/...
eventsRef.push().setValue(mapOf("name" to "Coding")) // a different auto-idFormula
push for lists, setValue for a single item
This is the write rule to remember. Use setValue on a fixed path when there is exactly one thing there (a setting, a specific record you know the key of). Use push() when adding items to a collection: push generates a unique auto-id child key, so each new event or registration gets its own slot and nothing overwrites anything.
Get this wrong, calling setValue on the same list path repeatedly, and each write replaces the last, silently losing data. push() is what lets a list grow safely. When in doubt, if you are adding to a collection, push.
Quiz
You are adding many registrations to a 'registrations' list in the Realtime Database. Why use ref.push().setValue(...) rather than ref.setValue(...) on the same path each time?
- push is just a shorter way to write setValue
- push() generates a unique key for each item, so registrations do not overwrite each other, whereas setValue on the same path replaces the previous value
- setValue does not work with the Realtime Database
- push encrypts the data
Show the answer
push() generates a unique key for each item, so registrations do not overwrite each other, whereas setValue on the same path replaces the previous value
push() creates a unique auto-generated key for each new child, so every registration is stored in its own slot and the list can grow without items clobbering one another. Calling setValue on the same fixed path repeatedly would OVERWRITE the previous value each time, keeping only the last registration, a data-loss bug. Option A is wrong: push is not merely shorthand; it changes behaviour by generating a new unique key. Option C is false: setValue works fine (it is the correct tool for a single known location). Option D is invented; push does not encrypt anything. For collections, push to get a unique key per item; for a single known location, setValue.
Think first
How does push() guarantee unique keys without a central counter?
Many devices could push at once. How does push() avoid two items getting the same key, with no central id server? Then tap.
Show the answer
Because push() generates keys that are both TIME-ORDERED and RANDOM, engineered so that even many clients pushing simultaneously produce different keys without needing to coordinate through a central counter. A naive approach, 'ask a server for the next number', would be a bottleneck and would struggle offline or under heavy concurrency. Instead, a Firebase push key is built from two ingredients: a timestamp (so keys sort in the order items were added, which is handy for chronological lists) and a chunk of random bits. The timestamp portion makes keys from different moments naturally distinct and ordered; the random portion makes keys generated in the SAME millisecond, even on different devices, still almost certainly different, because the odds of two random components colliding are astronomically small. Crucially, this means a client can generate a valid, unique key entirely on its own, instantly, even while OFFLINE, with no round trip to a server, and be confident it will not clash with keys made by other clients. That is a big deal for a real-time, multi-device, offline-capable database: writes never have to wait for a central authority to hand out ids. So push() gives you unique, time-sortable keys through clever local generation rather than central coordination, which is exactly why it is the right tool for growing shared lists. Time plus randomness, generated locally, yields keys that are unique without a coordinator.
Summary
Key takeaways
- To write to the Realtime Database, point a reference at a path and call setValue.
- setValue(data) writes a value at that path, replacing whatever was there; use it for a single, known location.
- For lists/collections, use push() to generate a unique auto-id child key, then setValue on it.
- push() lets a list grow without items overwriting each other; setValue on a fixed path would replace the previous value.
- The rule: push for adding to a collection, setValue for a single known item.
- Writes are asynchronous (they return a Task you can optionally handle); you can write primitives, maps, or simple objects.
- Memory hook: setValue writes/overwrites at a path, push makes a unique key for each new list item.