DataStore & Preferences Interview Questions

DATA › Storage

When would you choose Proto DataStore over Preferences DataStore for a real feature, and what's the actual cost of that choice?

What a strong answer covers: Proto DataStore earns its keep when you have structured, evolving data with real type safety needs, like a settings object with nested fields, because the schema is compile-time checked and you get real objects instead of stringly-typed keys. The cost is real: you write a .proto schema, generate code, write a Serializer for encode/decode, and now schema evolution has to follow protobuf's field-numbering rules, which is meaningfully more setup than Preferences DataStore's just-add-a-key model, so it's overkill for a handful of simple flags.

Walk me through how you'd migrate a legacy app's years of accumulated SharedPreferences into DataStore without losing user settings or racing with in-flight reads/writes during the cutover.

What a strong answer covers: You'd configure the DataStore builder with a SharedPreferencesMigration pointing at the old prefs file, which Jetpack runs automatically and exactly once before the DataStore's data is first accessed, copying over the values and letting you optionally exclude keys you don't want migrated. The race to watch for is any code path still reading the old SharedPreferences directly during the transition window, since DataStore's migration only fires when DataStore itself is first touched, so you generally want to route all reads/writes through DataStore immediately and stop touching the old SharedPreferences instance in parallel.

DataStore's edit { } model is built around applying an atomic transform to the current preferences. What bugs show up when a team ignores that and reads a value, mutates some external variable, then writes it back separately?

What a strong answer covers: Reading outside the transform and writing back later reintroduces the exact lost-update race DataStore's transactional edit{} was built to prevent: two concurrent writers can both read the old value, apply their own change, and the second write silently clobbers the first one's update. The fix is doing the read-modify-write entirely inside the edit{} lambda, since DataStore serializes those transforms, guaranteeing each one sees the latest committed state rather than a stale snapshot captured earlier.

Back to DataStore & Preferences