Skip to content

[Due for payment 2026-06-09] [Onyx Audit] Remove initWithStoredValues from useOnyx #80091

Closed

Description

@fabioh8010

Coming from #71202.

In order to simplify useOnyx API (and consequently Onyx) let's work on proposing the removal of some configurations we think are anti-patterns / unnecessary at this point.

Last year @roryabraham drafted this proposal that can be found in this doc, but I will put it below in case you don't have access. We should review the proposal, adjust if necessary and post it.

Original proposal from Rory

Proposal: Introduce RAM-only Onyx keys.

Background

react-native-onyx is a very versatile state management library that is the beating heart of our front-end. It largely relies on a publisher-subscriber (PubSub) pattern to propagate data across various front-end UI components. Furthermore, one of the driving principles of Onyx is supporting a snappy, optimistic, offline-first approach that couples data storage with state management.

Furthermore, we have built systems in our back-end that are tightly coupled with Onyx. Colloquially these systems are often referred to as “reliable updates” or just “Onyx updates”. I like to think of Onyx as a small copy of the back-end database, with just the data that a particular user needs and has access to.

In most cases, and in particular for pieces of data that originate in the back-end, persisting data and then reading it from disk makes sense for our use-cases. However, there are some pieces of data which are ephemeral - short-lived, and not representative of some permanent state. Some examples of this are:

  • Is your device offline?
  • Are we fetching some data from the back-end?

As a litmus test, if the answer to both of the following questions is yes, then the data is probably ephemeral:

  • If I kill the app and open it again, would this data still be accurate?
  • Does this data exist only on the client, or is it coming from the server?

We have a way to handle ephemeral data in Onyx - initWithStoredValues. This boolean parameter to useOnyx and Onyx.connectWithoutView defaults to true, but if it’s false, then the first time the data is requested it will not be read from cache or disk immediately, preventing the consumption of stale data stored in Onyx with the same key.

Regardless of whether consumers of a piece of Onyx data pass initWithStoredValues: false, all Onyx data is persisted to disk - that’s just the internal design of Onyx.

Problem

When developers forget (or don’t know) to pass initWithStoredValues: false to useOnyx invocations accessing an ephemeral piece of data, stale data is read from disk, which causes bugs (example).

Solution

Introduce the concept of RAM-only Onyx keys. The way this would work is that Onyx keys can be denoted with the ramonly_ prefix, and then Onyx will not ever write that data to disk, preventing it from ever being read from disk in a stale state. Then deprecate and remove initWithStoredValues from Onyx.

This solves the core problem in that ephemeral data can be configured once in Onyx.init, and all usages of that data will implicitly be treated as such. But it also has some tertiary advantages:

  • Simpler: You can’t read stale data from disk if you never write it to disk in the first place.
  • More efficient: When we write data to disk with the intention of never reading it from disk, that wastes time and computer resources.
Issue OwnerCurrent Issue Owner: @Krishna2323
Pinned by tgolen

Activity

  1. moved this from LOW to HIGH in [#whatsnext] #qualityon Jan 22, 2026
  2. JKobrynski commented on Jan 22, 2026

    @JKobrynski
    Contributor

    Hi, I'm Julian from Callstack - expert agency - and I'd like to work on this issue

  3. self-assigned this
    on Jan 22, 2026
  4. JKobrynski commented on Jan 22, 2026

    @JKobrynski
    Contributor

    Update:

    I started working on this issue today. I got familiar with Rory's proposal that he posted some months ago and started exploring how we can introduce it to the current codebase. I'm going to continue my work tomorrow.

  5. fabioh8010 commented on Jan 23, 2026

    @fabioh8010
    ContributorAuthor

    Some suggestions to the original proposal:

    • Rephrasing second paraghraph to be less "personal"
      • Furthermore, we have built systems in our back-end that are tightly coupled with Onyx. Colloquially these systems are often referred to as “reliable updates” or just “Onyx updates”. We can think of Onyx as a small copy of the back-end database, with just the data that a particular user needs and has access to.

    • In Solution section instead of using a prefix ramonly_ to identify RAM-only keys, we could use a specific entry in ONYXKEYS to group all these keys e.g. ONYXKEYS.RAM_ONLY.<key> just like we have for collection ones (ONYXKEYS.COLLECTION.<key>). In this way I think logic handling inside Onyx will also be easier because it will be cheaper to know if that key is ram-only or not by just checking a Set, instead of performin string operations to check for the prefix.
    • Explain more in Solution section what we plan to do in steps, e.g.
      1. Implement support for RAM-only keys in the react-native-onyx and mark the initWithStoredValues prop as deprecated.
      2. Replace initWithStoredValues instances in the E/App with the new approach.
      3. Ultimately, remove initWithStoredValues from Onyx.

    WDYT @JKobrynski @roryabraham ?

  6. JKobrynski commented on Jan 23, 2026

    @JKobrynski
    Contributor

    @fabioh8010

    1. By "less personal", you mean rephasing to avoid words like "we"?
    2. Grouping these keys like we do for collections is a great idea imo! But we should keep the ramonly_ prefix in key's name right? E.g. SOME_RAMONLY_KEY: 'ramonly_SOME_KEY' right?
    3. Agreed
  7. fabioh8010 commented on Jan 23, 2026

    @fabioh8010
    ContributorAuthor

    @JKobrynski

    By "less personal", you mean rephasing to avoid words like "we"?

    I left a suggestion in my previous answer. Before it was "I like to think of Onyx as..." and I changed to "We can think of Onyx as...".

    Grouping these keys like we do for collections is a great idea imo! But we should keep the ramonly_ prefix in key's name right? E.g. SOME_RAMONLY_KEY: 'ramonly_SOME_KEY' right?

    If we agree on the grouping I don't think we would need to prefix anymore, would sound redundant to me.

  8. JKobrynski commented on Jan 23, 2026

    @JKobrynski
    Contributor

    Here is the updated version of Rory's proposal (this is still a draft, so it might be changed, I'm happy to address any feedback!):

    Proposal:

    Introduce RAM-only Onyx keys.

    Background

    react-native-onyx is a very versatile state management library that is the beating heart of our front-end. It largely relies on a publisher-subscriber (PubSub) pattern to propagate data across various front-end UI components. Furthermore, one of the driving principles of Onyx is supporting a snappy, optimistic, offline-first approach that couples data storage with state management.

    Furthermore, we have built systems in our back-end that are tightly coupled with Onyx. Colloquially these systems are often referred to as “reliable updates” or just “Onyx updates”. We can think of Onyx as a small copy of the back-end database, with just the data that a particular user needs and has access to.

    In most cases, and in particular for pieces of data that originate in the back-end, persisting data and then reading it from disk makes sense for our use-cases. However, there are some pieces of data which are ephemeral - short-lived, and not representative of some permanent state. Some examples of this are:

    • Is your device offline?
    • Are we fetching some data from the back-end?

    As a litmus test, if the answer to both of the following questions is yes, then the data is probably ephemeral:

    • If I kill the app and open it again, would this data still be accurate?
    • Does this data exist only on the client, or is it coming from the server?

    We have a way to handle ephemeral data in Onyx - initWithStoredValues. This boolean parameter to useOnyx and Onyx.connect defaults to true, but if it’s false, then the first time the data is requested it will not be read from cache or disk immediately, preventing the consumption of stale data stored in Onyx with the same key.

    Regardless of whether consumers of a piece of Onyx data pass initWithStoredValues: false, all Onyx data is persisted to disk - that’s just the internal design of Onyx.

    Problem

    When developers forget (or don’t know) to pass initWithStoredValues: false to useOnyx invocations accessing an ephemeral piece of data, stale data is read from disk, which causes bugs (example).

    Solution

    Introduce the concept of RAM-only Onyx keys. The way this would work is that Onyx keys could be grouped, similar to what we do with collections (e.g. like ONYXKEYS.RAM_ONLY.<key>), and then Onyx will never write that data to disk, preventing it from being read from disk in a stale state. Then deprecate and remove initWithStoredValues from Onyx.

    This solves the core problem in that ephemeral data can be configured once in Onyx.init, and all usages of that data will implicitly be treated as such. But it also has some tertiary advantages:

    • Simpler: You can’t read stale data from disk if you never write it to disk in the first place.
    • More efficient: When we write data to disk with the intention of never reading it from disk, that wastes time and computer resources.

    The process would proceed as follows:

    1. Implement support for RAM-only keys in react-native-onyx and mark the initWithStoredValues property as deprecated
    2. Replace initWithStoredValues instances in the E/App with RAM-only Onyx keys.
    3. Ultimately, remove initWithStoredValues from Onyx.

    CC: @roryabraham

  9. JKobrynski commented on Jan 23, 2026

    @JKobrynski
    Contributor

    Update:

    I had a discussion with @fabioh8010 about how we can update the original proposal. I rewrote the proposal with the changes that we agreed on. I posted the draft version of the proposal in a comment above so Rory can share his thoughts about it before it's posted for external review. While I'm waiting for Rory's feedback on the draft, I'm already looking into the react-native-onyx codebase to find out how we can implement the suggested changes.

  10. 224 remaining items

  11. Krishna2323 commented on Jun 2, 2026

    @Krishna2323
    Contributor

    Hey @mountiny @roryabraham, everything seems to be deployed and done here. Requesting a compensation increase for the reviewer role on this issue.

    Breakdown:

    That said, I'm completely open to any adjustments the team sees fit. Thank you!

  12. roryabraham commented on Jun 2, 2026

    @roryabraham
    Contributor

    @Krishna2323 $1875 sounds reasonable to me 👍🏼

  13. melvin-bot commented on Jun 5, 2026

    @melvin-bot

    @Krishna2323 Whoops! This issue is 2 days overdue. Let's get this updated quick!

  14. melvin-bot commented on Jun 8, 2026

    @melvin-bot

    Current assignee @mallenexpensify is eligible for the Awaiting Payment assigner, not assigning anyone new.

  15. Krishna2323 commented on Jun 8, 2026

    @Krishna2323
    Contributor

    @mallenexpensify this is ready for payment, and I don't think a checklist is required here. The payment summary is above ^

  16. melvin-bot commented on Jun 12, 2026

    @melvin-bot

    @Krishna2323 Whoops! This issue is 2 days overdue. Let's get this updated quick!

  17. Krishna2323 commented on Jun 15, 2026

    @Krishna2323
    Contributor

    this is ready for payment, and I don't think a checklist is required here. The payment summary is above ^

    @mallenexpensify friendly bump :)

  18. mallenexpensify commented on Jun 15, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor+: @Krishna2323 due $1875 via NewDot

  19. laurenreidexpensify commented on Jun 29, 2026

    @laurenreidexpensify
    Contributor

    $1875 approved for @Krishna2323

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionDailyKSv2Task

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions