Skip to content

Add retry backoff for connection errors in OnyxUtils.retryOperation #87782

Closed

Description

@Julesssss

Errors #1, #3, #5 from the storage error investigation account for 51.7% of all failures and are transient connection issues. OnyxUtils.retryOperation currently retries immediately with no delay, which is ineffective — the DB connection needs time to recover.

Explore adding exponential backoff or an alternative retry mechanism for these connection-class errors.

Parent issue: #85252

Issue OwnerCurrent Issue Owner: @leshniak

Activity

  1. added
    ImprovementItem broken or needs improvement.
    InternalRequires API changes or must be handled by Expensify staff
    on Apr 13, 2026
  2. leshniak commented on Apr 15, 2026

    @leshniak
    Contributor

    I am Maciej from Callstack - I can work on this.

  3. leshniak commented on Apr 17, 2026

    @leshniak
    Contributor

    VictoriaLogs Investigation — Key Findings

    Assumption tested: Exponential backoff will improve retry success rate for connection errors.

    What data showed:

    1. 0% recovery rate at 0ms delay — All 5 retry attempts fail at the same rate (~67K each). No attempt succeeds more than any other. Flat curve, not declining.

    2. 100% exhaustion — Every retry chain that starts, finishes all 5 attempts and gives up. 67,404 operations hit MAX_STORAGE_OPERATION_RETRY_ATTEMPTS.

    3. IDB is degraded, not dead — Users who exhaust retries on one key continue successfully writing to other keys in the same session. Example: one user had 28K successful writes alongside exhausted retries.

    What this means:

    • Immediate retry (0ms) provably doesn't work — the DB needs recovery time
    • But we have no production data on whether any delay helps, because delay was never tried
    • The failure pattern (100% exhaustion, flat across attempts) is consistent with "too fast to recover" but also consistent with "permanently broken for that key"

    Tradeoff:

    If backoff helps If backoff doesn't help
    ~1.74M errors/month reduced ~3.1s wasted per failed chain (vs ~0ms today)
    Silent data loss prevented No user-visible regression (writes already fail)

    Honest framing: Backoff is a well-reasoned bet, not a proven fix. The PR adds instrumentation (connection error logging with delay info) so we can measure actual recovery rates in production.

  4. Julesssss commented on Apr 17, 2026

    @Julesssss
    ContributorAuthor

    Thanks for investigating. It seems we should drop this and just stick with the main improvements. LMK if you dissagree

  5. leshniak commented on Apr 20, 2026

    @leshniak
    Contributor

    @Julesssss I think it's worth trying. With the current logs I can't say with confidence that it will fix the issue, but there is a chance. It doesn't break anything.

  6. Julesssss commented on Apr 20, 2026

    @Julesssss
    ContributorAuthor

    Okay fair enough, lets test delay. Could you suggest a plan here for what/when we'll measure exactly. And what would lead us to rolling back.

  7. leshniak commented on Apr 30, 2026

    @leshniak
    Contributor

    Hey @Julesssss, sorry for the delay!

    I just pushed observability improvements to the Onyx PR — the original version only logged retry attempts but not outcomes, which would have made the experiment unmeasurable. Now we have three distinct log signals:

    1. Connection error detected, retrying with backoff ({delay}ms) — on each retry attempt (was already there)
    2. Connection error recovered after backoff on attempt {N}/5 — when a retry succeeds after backoff (new)
    3. Connection error exhausted all retries with backoff — when all 5 retries fail (new, distinct from generic exhaustion)

    Measurement plan

    What to measure (via VictoriaLogs queries on the 3 signals above):

    • Recovery rate: count of "recovered" logs / count of "detected" logs — this is the core metric. Current baseline is 0% with immediate retries
    • Recovery distribution by attempt: which attempt (1-5) recoveries happen on most — tells us if the delay schedule is right
    • Exhaustion rate: count of "exhausted" logs — should decrease if backoff helps

    When:

    • Deploy to staging first, verify logs appear correctly
    • 1 week of production data should be sufficient given the volume (~67k failures/week from the investigation)

    Rollback criteria:

    • Recovery rate stays ~0% after 1 week → backoff doesn't help, pivot to fail-fast or IDB reconnection strategy
    • Any regression in overall Onyx operation success rate (compare week-over-week) → immediate revert
    • Unexpected latency impact from the ~3.1s max total delay → revert (though this only affects already-failing operations, so impact should be negligible)

    Success criteria:

    • Recovery rate meaningfully above 0% (even 10-20% would validate the approach and we'd tune the delay constants)
  8. Julesssss commented on Apr 30, 2026

    @Julesssss
    ContributorAuthor

    No worries, plan looks good to me. Lets get the PR open for review and then we'll need to wait a bit while Onyx slowly gets bumped 👍

  9. fabioh8010 commented on May 12, 2026

    @fabioh8010
    Contributor

    @leshniak @Julesssss I propose we hold this idea/PR until we have proper DB healing mechanisms in Onyx as detailed here. I feel that if we have cases when the storage write is repeatedly and instantly failing (like Internal error opening backing store for indexedDB.open.) the first and best goal is probably on focus on the healing strategy. Then we can think about implement retry backoff for specific cases.

  10. Julesssss commented on May 12, 2026

    @Julesssss
    ContributorAuthor

    I propose we hold this idea/PR until we have proper DB healing mechanisms in Onyx as detailed #87862 (comment).

    Yeah that makes sense, thanks for jumping in, lets discuss further in the linked issue.

  11. fabioh8010 commented on Jul 8, 2026

    @fabioh8010
    Contributor

    @elirangoshen is taking over to verify if we need this retry backoff logic since he did a recent audit over the storage errors.

  12. melvin-bot commented on Jul 13, 2026

    @melvin-bot

    @leshniak, @Julesssss, @fabioh8010, this Monthly task hasn't been acted upon in 6 weeks; closing.

    If you disagree, feel encouraged to reopen it -- but pick your least important issue to close instead.

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

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions